home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / sd-26.zip / sdbasic.c < prev    next >
C/C++ Source or Header  |  1992-09-09  |  100KB  |  2,138 lines

  1. /* SD -- square dance caller's helper.
  2.  
  3.     Copyright (C) 1990, 1991, 1992  William B. Ackerman.
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     This is for version 25. */
  20.  
  21. /* This defines the following functions:
  22.    mirror_this
  23.    basic_move
  24. */
  25.  
  26. #include "sd.h"
  27.  
  28.  
  29.  
  30. extern void mirror_this(setup *s)
  31.  
  32. {
  33.    int l, r, z, i, n;
  34.    setup temp;
  35.    coordrec *cptr;
  36.    int x, y, place, limit;
  37.  
  38.    temp = *s;
  39.  
  40.    cptr = nice_setup_coords[s->kind];
  41.    if (!cptr) fail("Don't recognize ending setup for this call; not able to do it mirror.");
  42.    limit = setup_limits[s->kind];
  43.  
  44.    if (s->rotation & 1) {
  45.       for (i=0; i<=limit; i++) {
  46.          x = cptr->xca[i];
  47.          y = - cptr->yca[i];
  48.          place = cptr->numbers[3-(y >> 2)] [(x >> 2)+4];
  49.  
  50.          if (place < 0) fail("Don't recognize ending setup for this call, not able to do it mirror.");
  51.          if ((cptr->xca[place] != x) || (cptr->yca[place] != y))
  52.             fail("Don't recognize ending setup for this call, not able to do it mirror.");
  53.  
  54.          n = temp.people[i].id1;
  55.          l = (n & ROLLBITL) >> 2;
  56.          r = (n & ROLLBITR) << 2;
  57.          z = (n & ~(ROLLBITL | ROLLBITR)) | l | r;
  58.          s->people[place].id1 = (z & 010) ? (z ^ 2) : z;
  59.          s->people[place].id2 = temp.people[i].id2;
  60.       }
  61.    }
  62.    else {
  63.       for (i=0; i<=limit; i++) {
  64.          x = - cptr->xca[i];
  65.          y = cptr->yca[i];
  66.          place = cptr->numbers[3-(y >> 2)] [(x >> 2)+4];
  67.  
  68.          if (place < 0) fail("Don't recognize ending setup for this call, not able to do it mirror.");
  69.          if ((cptr->xca[place] != x) || (cptr->yca[place] != y))
  70.             fail("Don't recognize ending setup for this call, not able to do it mirror.");
  71.  
  72.          n = temp.people[i].id1;
  73.          l = (n & ROLLBITL) >> 2;
  74.          r = (n & ROLLBITR) << 2;
  75.          z = (n & ~(ROLLBITL | ROLLBITR)) | l | r;
  76.          s->people[place].id1 = (z & 1) ? (z ^ 2) : z;
  77.          s->people[place].id2 = temp.people[i].id2;
  78.       }
  79.    }
  80. }
  81.  
  82.  
  83.  
  84. typedef struct {
  85.    int size;                 /* how many people in the maps */
  86.    int lmask;                /* which people are facing E-W in original double-length setup */
  87.    int rmask;                /* where in original setup can people be found */
  88.    int cmask;                /* where in original setup have people collided */
  89.    int source[12];           /* where to get the people */
  90.    int map0[12];             /* where to put the north (or east)-facer */
  91.    int map1[12];             /* where to put the south (or west)-facer */
  92.    setup_kind initial_kind;  /* what setup they are collided in */
  93.    setup_kind final_kind;    /* what setup to change it to */
  94.    int rot;                  /* whether to rotate final setup CW */
  95.    } collision_map;
  96.  
  97. static collision_map collision_map_table[] = {
  98.    /* These items handle various types of "1/2 circulate" calls from 2x4's. */
  99.    {4, 0x0CC0CC, 0xCC, 0xCC, {2, 3, 6, 7},         {0, 3, 5, 6},          {1, 2, 4, 7},           s_crosswave, s1x8,        1},   /* from lines in */
  100.    {4, 0x000000, 0x33, 0x33, {0, 1, 4, 5},         {0, 3, 5, 6},          {1, 2, 4, 7},           s_crosswave, s1x8,        0},   /* from lines out */
  101.    {4, 0x022022, 0xAA, 0xAA, {1, 3, 5, 7},         {2, 5, 7, 0},          {3, 4, 6, 1},           s_spindle,   s_crosswave, 0},   /* from trade by */
  102.    {6, 0x0880CC, 0xDD, 0x88, {0, 2, 3, 4, 6, 7},   {7, 0, 1, 3, 4, 6},    {7, 0, 2, 3, 4, 5},     s_crosswave, s_3x1dmd,    1},   /* from 3&1 lines w/ centers in */
  103.    {6, 0x000044, 0x77, 0x22, {0, 1, 2, 4, 5, 6},   {0, 1, 3, 4, 6, 7},    {0, 2, 3, 4, 5, 7},     s_crosswave, s_3x1dmd,    0},   /* from 3&1 lines w/ centers out */
  104.    {6, 0x0440CC, 0xEE, 0x44, {1, 2, 3, 5, 6, 7},   {7, 0, 2, 3, 5, 6},    {7, 1, 2, 3, 4, 6},     s_crosswave, s_3x1dmd,    1},   /* from 3&1 lines w/ ends in */
  105.    {4, 0x088088, 0x99, 0x99, {0, 3, 4, 7},         {0, 2, 5, 7},          {1, 3, 4, 6},           s_crosswave, s_crosswave, 0},   /* from inverted lines w/ centers in */
  106.    {4, 0x044044, 0x66, 0x66, {1, 2, 5, 6},         {6, 0, 3, 5},          {7, 1, 2, 4},           s_crosswave, s_crosswave, 1},   /* from inverted lines w/ centers out */
  107.    /* These items handle parallel lines with people wedged on one end, and hence handle flip or cut the hourglass. */
  108.    {6, 0x000000, 0x77, 0x11, {0, 1, 2, 4, 5, 6},   {0, 2, 3, 7, 8, 9},    {1, 2, 3, 6, 8, 9},     s2x4,        s2x6,        0},
  109.    {6, 0x000000, 0xEE, 0x88, {1, 2, 3, 5, 6, 7},   {2, 3, 4, 8, 9, 11},   {2, 3, 5, 8, 9, 10},    s2x4,        s2x6,        0},
  110.    /* These items handle single lines with people wedged on one end, and hence handle flip or cut the diamond. */
  111.    {3, 0x000000, 0x0B, 0x01, {0, 1, 3},            {0, 2, 5},             {1, 2, 5},              s1x4,        s_1x6,       0},
  112.    {3, 0x000000, 0x0E, 0x04, {1, 2, 3},            {2, 4, 5},             {2, 3, 5},              s1x4,        s_1x6,       0},
  113.    /* These items handle columns with people wedged everywhere, and hence handle unwraps of facing diamonds etc. */
  114.    {4, 0x055055, 0x55, 0x55, {0, 2, 4, 6},         {12, 14, 2, 11},       {10, 3, 4, 6},          s2x4,        s4x4,        0},
  115.    {4, 0x0AA0AA, 0xAA, 0xAA, {1, 3, 5, 7},         {13, 0, 7, 9},         {15, 1, 5, 8},          s2x4,        s4x4,        0},
  116.    /* These items handle the situation from a 2FL/intlkd box circ/split box trade circ. */
  117.    {2, 0x000000, 0x03, 0x03, {0, 1},               {0, 2},                {1, 3},                 s2x4,        s2x4,        0},
  118.    {2, 0x000000, 0x0C, 0x0C, {2, 3},               {0, 2},                {1, 3},                 s2x4,        s2x4,        0},
  119.    {2, 0x000000, 0x30, 0x30, {5, 4},               {7, 5},                {6, 4},                 s2x4,        s2x4,        0},
  120.    {2, 0x000000, 0xC0, 0xC0, {7, 6},               {7, 5},                {6, 4},                 s2x4,        s2x4,        0},
  121.    /* These items handle various types of "1/2 circulate" calls from 2x2's. */
  122.    {2, 0x000000, 0x05, 0x05, {0, 2},               {0, 3},                {1, 2},                 sdmd,        s1x4,        0},   /* from couples out */
  123.    {2, 0x00A00A, 0x0A, 0x0A, {1, 3},               {0, 3},                {1, 2},                 sdmd,        s1x4,        1},   /* from couples in */
  124.    {2, 0x000000, 0x05, 0x05, {0, 2},               {0, 3},                {1, 2},                 s1x4,        s1x4,        0},
  125.    {2, 0x00A00A, 0x0A, 0x0A, {1, 3},               {0, 3},                {1, 2},                 s1x4,        s1x4,        0},
  126.    {2, 0x000000, 0x06, 0x06, {1, 2},               {0, 3},                {1, 2},                 s1x4,        s1x4,        0},   /* from "head pass thru, all split circulate" */
  127.    {2, 0x000000, 0x09, 0x09, {0, 3},               {0, 3},                {1, 2},                 s1x4,        s1x4,        0},   /* from "head pass thru, all split circulate" */
  128.    /* These items handle "1/2 split trade circulate" from 2x2's. */
  129.    {3, 0x008008, 0x0D, 0x08, {0, 2, 3},            {0, 2, 1},             {0, 2, 3},              sdmd,        sdmd,        0},
  130.    {3, 0x002002, 0x07, 0x02, {0, 2, 1},            {0, 2, 1},             {0, 2, 3},              sdmd,        sdmd,        0},
  131.    /* These items handle various types of "circulate" calls from 2x2's. */
  132.    {2, 0x009009, 0x09, 0x09, {0, 3},               {7, 5},                {6, 4},                 s2x2,        s2x4,        1},   /* from box facing all one way */
  133.    {2, 0x006006, 0x06, 0x06, {1, 2},               {0, 2},                {1, 3},                 s2x2,        s2x4,        1},   /* we need all four cases */
  134.    {2, 0x000000, 0x0C, 0x0C, {2, 3},               {5, 7},                {4, 6},                 s2x2,        s2x4,        0},   /* sigh */
  135.    {2, 0x000000, 0x03, 0x03, {0, 1},               {0, 2},                {1, 3},                 s2x2,        s2x4,        0},   /* sigh */
  136.    /* These items handle more 2x2 stuff, including the "special drop in" that makes chain reaction/motivate etc. work. */
  137.    {2, 0x005005, 0x05, 0x05, {0, 2},               {7, 2},                {6, 3},                 s2x2,        s2x4,        1},
  138.    {2, 0x00A00A, 0x0A, 0x0A, {1, 3},               {0, 5},                {1, 4},                 s2x2,        s2x4,        1},
  139.    {2, 0x000000, 0x05, 0x05, {0, 2},               {0, 5},                {1, 4},                 s2x2,        s2x4,        1},
  140.    {2, 0x000000, 0x0A, 0x0A, {1, 3},               {2, 7},                {3, 6},                 s2x2,        s2x4,        1},
  141.    {-1}};
  142.  
  143.  
  144. static void fix_collision(
  145.    int collision_mask,
  146.    int collision_index,
  147.    int result_mask,
  148.    setup *result)
  149.  
  150. {
  151.    int temprot, lowbitmask;
  152.    int i;
  153.    collision_map *c_map_ptr;
  154.    setup spare_setup;
  155.  
  156.    spare_setup = *result;
  157.    clear_people(result);
  158.  
  159.    lowbitmask = 0;
  160.    for (i=0; i<24; i++) {
  161.       lowbitmask |= ((spare_setup.people[i].id1) & 1) << i;
  162.    }
  163.  
  164.    c_map_ptr = collision_map_table;
  165.    for (;;) {
  166.       if (c_map_ptr->size < 0) break;
  167.       if ((result->kind == c_map_ptr->initial_kind) && ((lowbitmask == c_map_ptr->lmask)) && (result_mask == c_map_ptr->rmask) && (collision_mask == c_map_ptr->cmask))
  168.          goto win;
  169.       c_map_ptr++;
  170.    }
  171.  
  172.    /* Don't recognize the pattern, report this as normal collision. */
  173.    collision_person1 = spare_setup.people[collision_index].id1;
  174.    collision_person2 = spare_setup.people[collision_index+12].id1;
  175.    error_message1[0] = '\0';
  176.    error_message2[0] = '\0';
  177.    longjmp(longjmp_ptr->the_buf, 3);
  178.  
  179.    win:
  180.  
  181.    warn(warn__take_right_hands);
  182.    temprot = ((-c_map_ptr->rot) & 3) * 011;
  183.    result->kind = c_map_ptr->final_kind;
  184.    result->rotation += c_map_ptr->rot;
  185.  
  186.    for (i=0; i<c_map_ptr->size; i++) {
  187.       int oldperson;   
  188.  
  189.       oldperson = spare_setup.people[c_map_ptr->source[i]].id1;
  190.       if (oldperson & 2)
  191.          install_rot(result, c_map_ptr->map1[i], &spare_setup, c_map_ptr->source[i], temprot);
  192.       else
  193.          install_rot(result, c_map_ptr->map0[i], &spare_setup, c_map_ptr->source[i], temprot);
  194.       oldperson = spare_setup.people[c_map_ptr->source[i]+12].id1;
  195.       if (oldperson & 2)
  196.          install_rot(result, c_map_ptr->map1[i], &spare_setup, c_map_ptr->source[i]+12, temprot);
  197.       else
  198.          install_rot(result, c_map_ptr->map0[i], &spare_setup, c_map_ptr->source[i]+12, temprot);
  199.    }
  200. }
  201.  
  202.  
  203. static int identity[24] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
  204. static int ftc2x4[8] = {10, 15, 3, 1, 2, 7, 11, 9};
  205. static int ftl2x4[12] = {6, 11, 15, 13, 14, 3, 7, 5, 6, 11, 15, 13};
  206. static int galtranslateh[16] = {0, 3, 4, 2, 0, 0, 0, 5, 0, 7, 0, 6, 0, 0, 0, 1};
  207. static int galtranslatev[16] = {0, 0, 0, 1, 0, 3, 4, 2, 0, 0, 0, 5, 0, 7, 0, 6};
  208. static int dmdhyperh[12] = {0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0};
  209. static int linehyperh[12] = {0, 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0};
  210. static int galhyperh[12] = {6, 0, 0, 0, 3, 1, 2, 0, 4, 0, 7, 5};
  211. static int dmdhyperv[12] = {0, 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0};
  212. static int linehyperv[12] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 3, 0};
  213. static int galhyperv[12] = {0, 7, 5, 6, 0, 0, 0, 3, 1, 2, 0, 4};
  214. static int starhyperh[12] =  {0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0};
  215. static int fstarhyperh[12] = {0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0};
  216.  
  217.  
  218.  
  219. static void special_4_way_symm(
  220.    callarray *tdef,
  221.    setup *scopy,
  222.    personrec newpersonlist[],
  223.    int newplacelist[],
  224.    int *result_mask,
  225.    setup *result)
  226.  
  227. {
  228.    static int table_2x4[8] = {10, 15, 3, 1, 2, 7, 11, 9};
  229.    static int line_table[4] = {0, 1, 6, 7};
  230.    static int dmd_table[4] = {0, 4, 6, 10};
  231.  
  232.    int begin_size;
  233.    int real_index;
  234.    int real_direction, northified_index;
  235.    int z, k, zzz, result_size, result_quartersize;
  236.    int *the_table;
  237.  
  238.    switch (result->kind) {
  239.       case s2x2: case s_galaxy: case s_c1phan: case s4x4: case s_hyperglass: case s_star: case s_1x1:
  240.          the_table = 0;
  241.          break;
  242.       case s1x4:
  243.          result->kind = s_hyperglass;
  244.          the_table = line_table;
  245.          break;
  246.       case sdmd:
  247.          result->kind = s_hyperglass;
  248.          the_table = dmd_table;
  249.          break;
  250.       case s2x4:
  251.          result->kind = s4x4;
  252.          the_table = table_2x4;
  253.          break;
  254.       default:
  255.          fail("Don't recognize ending setup for this call.");
  256.    }
  257.  
  258.    begin_size = setup_limits[scopy->kind]+1;
  259.    result_size = setup_limits[result->kind]+1;
  260.    result_quartersize = result_size >> 2;
  261.    *result_mask = 0;
  262.  
  263.    for (real_index=0; real_index<begin_size; real_index++) {
  264.       personrec this_person = scopy->people[real_index];
  265.       newpersonlist[real_index].id1 = 0;
  266.       newpersonlist[real_index].id2 = 0;
  267.       if (this_person.id1) {
  268.          real_direction = this_person.id1 & 3;
  269.          northified_index = (real_index + (((4-real_direction)*begin_size) >> 2)) % begin_size;
  270.          z = find_calldef(tdef, scopy, real_index, real_direction, northified_index);
  271.          k = (z >> 4) & 017;
  272.          if (the_table) k = the_table[k];
  273.          k = (k + real_direction*result_quartersize) % result_size;
  274.          zzz = (z+real_direction*011) & 013;
  275.          newpersonlist[real_index].id1 = (this_person.id1 & ~(ROLLBITS | 077)) | zzz | ((z << 14) & ROLLBITS);
  276.          newpersonlist[real_index].id2 = this_person.id2;
  277.          newplacelist[real_index] = k;
  278.          *result_mask |= (1 << k);
  279.       }
  280.    }
  281. }
  282.  
  283.  
  284.  
  285. /* This function is internal. */
  286.  
  287. static void special_triangle(
  288.    callarray *cdef,
  289.    callarray *ldef,
  290.    setup *scopy,
  291.    personrec newpersonlist[],
  292.    int newplacelist[])
  293.  
  294. {
  295.    int real_index;
  296.    int real_direction, d2, northified_index;
  297.    int z, k;
  298.  
  299.    for (real_index=0; real_index<3; real_index++) {
  300.       personrec this_person = scopy->people[real_index];
  301.       newpersonlist[real_index].id1 = 0;
  302.       newpersonlist[real_index].id2 = 0;
  303.       newplacelist[real_index] = -1;
  304.       if (this_person.id1) {
  305.          real_direction = this_person.id1 & 3;
  306.          d2 = ((this_person.id1 >> 1) & 1) * 3;
  307.          northified_index = (real_index + d2);
  308.          z = find_calldef((real_direction & 1) ? cdef : ldef, scopy, real_index, real_direction, northified_index);
  309.          k = (((z >> 4) & 017) - d2);
  310.          if (k < 0) k += 6;
  311.          newpersonlist[real_index].id1 = (this_person.id1 & ~(ROLLBITS | 077)) | ((z + real_direction * 011) & 013) | ((z << 14) & ROLLBITS);
  312.          newpersonlist[real_index].id2 = this_person.id2;
  313.          newplacelist[real_index] = k;
  314.       }
  315.    }
  316. }
  317.  
  318.  
  319. /* For this routine, we know that callspec is a real call, with an array definition schema.
  320.    Also, result->people have been cleared. */
  321.  
  322. extern void basic_move(
  323.    setup *ss,
  324.    parse_block *parseptr,
  325.    callspec_block *callspec,
  326.    final_set final_concepts,
  327.    int tbonetest,
  328.    long_boolean fudged,
  329.    setup *result)
  330.  
  331. {
  332.    int i, j, k;
  333.    int livemask;
  334.    int newtb;
  335.    callarray *calldeflist;
  336.    long_boolean funny;
  337.    map_thing *division_maps;
  338.    begin_kind key1, key2;
  339.    callarray *ldef;
  340.    callarray *cdef;
  341.    callarray *linedefinition;
  342.    callarray *coldefinition;
  343.    callarray *goodies;
  344.    unsigned long int z;
  345.    int real_index, northified_index;
  346.    int num, halfnum, numout, halfnumout;
  347.    int collision_mask, collision_index;
  348.    int result_mask;
  349.    personrec newpersonlist[24];
  350.    int newplacelist[24];
  351.    int resultflags, desired_elongation, orig_elongation;
  352.    int inconsistent_rotation;
  353.    long_boolean four_way_startsetup;
  354.    long_boolean funny_ok1, funny_ok2;
  355.    calldef_block *qq;
  356.  
  357.    funny_ok1 = FALSE;
  358.    funny_ok2 = FALSE;
  359.  
  360.    /* We demand that the final concepts that remain be only those in the following list,
  361.       which includes all of the "heritable" concepts. */
  362.  
  363.    if (final_concepts &
  364.          ~(HERITABLE_FLAG_MASK | FINAL__SPLIT_SQUARE_APPROVED | FINAL__SPLIT_DIXIE_APPROVED | FINAL__SPLIT_SEQ_DONE | FINAL__TRIANGLE))
  365.       fail("This concept not allowed here.");
  366.  
  367.    newtb = tbonetest;
  368.    if (setup_limits[ss->kind] < 0) fail("Setup is extremely bizarre.");
  369.    resultflags = 0;
  370.    desired_elongation = 0;
  371.  
  372.    /* Set up the result elongation that we will need if the result is
  373.       a 2x2.  This comes from the original 2x2 elongation, or is set
  374.       perpendicular to the original 1x4/diamond elongation.  If the call has the
  375.       "parallel_conc_end" flag set, invert that elongation.
  376.       We will override all this if we divide a 1x4 or 2x2 into 1x2's. */
  377.  
  378.    switch (ss->kind) {
  379.       case s2x2:
  380.          desired_elongation = ((ss->setupflags & SETUPFLAG__ELONGATE_MASK) / SETUPFLAG__ELONGATE_BIT) * RESULTFLAG__ELONGATE_BIT;
  381.          break;
  382.       case s1x4: case sdmd:
  383.          desired_elongation = ((2 - (ss->rotation & 1)) * RESULTFLAG__ELONGATE_BIT);
  384.          break;
  385.    }
  386.  
  387.    orig_elongation = desired_elongation;   /* We may need this later. */
  388.  
  389.    if (callspec->callflags & cflag__parallel_conc_end) desired_elongation ^= RESULTFLAG__ELONGATE_MASK;
  390.    /* If the flags were zero and we complemented them so that both are set, that's not good. */
  391.    if (desired_elongation == RESULTFLAG__ELONGATE_MASK)
  392.       desired_elongation = 0;
  393.  
  394.    /* Many of the remaining final concepts (all of the heritable ones
  395.       except "funny" and "left", but "left" has been taken care of)
  396.       determine what call definition we will get. */
  397.  
  398.    z = final_concepts & HERITABLE_FLAG_MASK & ~FINAL__FUNNY;
  399.  
  400.    calldeflist = 0;
  401.  
  402.    for (qq = callspec->stuff.arr.def_list; qq; qq = qq->next) {
  403.       if (qq->modifier_set == z) {
  404.          if (qq->modifier_level > calling_level)
  405.             fail("Use of this modifier on this call is not allowed at this level.");
  406.          calldeflist = qq->callarray_list;
  407.          break;
  408.       }
  409.    }
  410.  
  411.    /* Calldeflist ought to have something now.  If not, the only excuse is that the concept
  412.       "magic" or "interlocked" was given, and the call has no special definition for same,
  413.       but wants us to divide the setup magically or interlockedly.  Or a similar thing with 12 matrix. */
  414.  
  415.    if (!calldeflist) {
  416.       unsigned long int y;
  417.       switch (ss->kind) {
  418.          case s2x4:
  419.             y = z & ~(FINAL__DIAMOND | FINAL__SINGLE | FINAL__CROSS | FINAL__GRAND);
  420.             if (y == FINAL__MAGIC) {
  421.                /* "Magic" was specified.  Split it into 1x4's in the appropriate magical way. */
  422.                division_maps = &map_2x4_magic;
  423.                final_concepts &= ~y;
  424.                goto divide_us;
  425.             }
  426.             break;
  427.          case s3x4:
  428.             if (z == FINAL__12_MATRIX) {
  429.                /* "12 matrix" was specified.  Split it into 1x4's in the appropriate way. */
  430.                division_maps = (*map_lists[s1x4][2])[MPKIND__SPLIT][1];
  431.                final_concepts &= ~z;
  432.                goto divide_us;
  433.             }
  434.             break;
  435.          case s2x6:
  436.             if (z == FINAL__12_MATRIX) {
  437.                /* "12 matrix" was specified.  Split it into 2x2's in the appropriate way. */
  438.                division_maps = (*map_lists[s2x2][2])[MPKIND__SPLIT][0];
  439.                final_concepts &= ~z;
  440.                goto divide_us;
  441.             }
  442.             break;
  443.          case s_qtag:
  444.             y = z & ~(FINAL__DIAMOND | FINAL__SINGLE | FINAL__CROSS | FINAL__GRAND);
  445.             if (y == FINAL__MAGIC) {
  446.                /* "Magic" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate magical way. */
  447.                division_maps = &map_qtg_magic;
  448.                final_concepts &= ~y;
  449.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  450.                goto divide_us;
  451.             }
  452.             else if (y == FINAL__INTERLOCKED) {
  453.                /* "Interlocked" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate interlocked way. */
  454.                division_maps = &map_qtg_intlk;
  455.                final_concepts &= ~y;
  456.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  457.                goto divide_us;
  458.             }
  459.             else if (y == (FINAL__INTERLOCKED | FINAL__MAGIC)) {
  460.                /* "Magic interlocked" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate disgusting way. */
  461.                division_maps = &map_qtg_magic_intlk;
  462.                final_concepts &= ~y;
  463.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  464.                goto divide_us;
  465.             }
  466.             break;
  467.          case s_ptpd:
  468.             y = z & ~(FINAL__DIAMOND | FINAL__SINGLE | FINAL__CROSS | FINAL__GRAND);
  469.             if (y == FINAL__MAGIC) {
  470.                /* "Magic" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate magical way. */
  471.                division_maps = &map_ptp_magic;
  472.                final_concepts &= ~y;
  473.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  474.                goto divide_us;
  475.             }
  476.             else if (y == FINAL__INTERLOCKED) {
  477.                /* "Interlocked" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate interlocked way. */
  478.                division_maps = &map_ptp_intlk;
  479.                final_concepts &= ~y;
  480.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  481.                goto divide_us;
  482.             }
  483.             else if (y == (FINAL__INTERLOCKED | FINAL__MAGIC)) {
  484.                /* "Magic interlocked" was specified, perhaps with "diamond".  Split it into diamonds in the appropriate disgusting way. */
  485.                division_maps = &map_ptp_magic_intlk;
  486.                final_concepts &= ~y;
  487.                resultflags |= RESULTFLAG__NEED_DIAMOND;      /* Indicate that we have done the division and the concept name needs to be changed. */
  488.                goto divide_us;
  489.             }
  490.             break;
  491.       }
  492.  
  493.       fail("Can't do this call with this modifier.");
  494.    }
  495.    
  496.    /* We now have an association list (setups ==> definition arrays) in calldeflist.
  497.       First, attend to a few details. */
  498.  
  499.    switch (ss->kind) {
  500.       case s2x2:
  501.          /* Now we do a special check for split-square-thru or split-dixie-style types of things. */
  502.          
  503.          if (final_concepts & FINAL__SPLIT_SQUARE_APPROVED) {
  504.             /* Find out who are facing each other directly and will therefore start. */
  505.    
  506.             if (((ss->people[2].id1 & d_mask) == d_west) && ((ss->people[3].id1 & d_mask) == d_east))
  507.                i = 0;
  508.             else if (((ss->people[3].id1 & d_mask) == d_north) && ((ss->people[0].id1 & d_mask) == d_south))
  509.                i = 1;
  510.             else if (((ss->people[0].id1 & d_mask) == d_east) && ((ss->people[1].id1 & d_mask) == d_west))
  511.                i = 2;
  512.             else if (((ss->people[1].id1 & d_mask) == d_south) && ((ss->people[2].id1 & d_mask) == d_north))
  513.                i = 3;
  514.             else
  515.                fail("People are not in correct position for split call.");
  516.  
  517.             j = (i + 1) & 3;
  518.             k = ss->people[i].id1;
  519.             z = ss->people[j].id1;
  520.  
  521.             /* Demand that the other people are facing the shoulders of the people who start. */
  522.             if (((k & (BIT_PERSON | 3)) != (i ^ (BIT_PERSON | 2))) || ((z ^ k) & d_mask))
  523.                fail("People are not in correct position for split call.");
  524.  
  525.             ss->people[i].id1 = rotccw(z);
  526.             ss->people[j].id1 = rotcw(k);
  527.             k = ss->people[i].id2;
  528.             z = ss->people[j].id2;
  529.             ss->people[i].id2 = z;
  530.             ss->people[j].id2 = k;
  531.             newtb = ss->people[0].id1 | ss->people[1].id1 | ss->people[2].id1 | ss->people[3].id1;
  532.          }
  533.          else if (final_concepts & FINAL__SPLIT_DIXIE_APPROVED) {
  534.             fail("Can't do split dixie stuff -- sorry.");
  535.          }
  536.          break;
  537.       case s_qtag:
  538.          if (fudged && !(callspec->callflags & cflag__fudge_to_q_tag))
  539.             fail("Can't do this call from arbitrary 3x4 setup.");
  540.          break;
  541.    }
  542.  
  543.   /* Now search the association list for an entry matching the setup we have, or else
  544.      divide the setup until we find something. */
  545.  
  546.    linedefinition = (callarray *) 0;
  547.    coldefinition = (callarray *) 0;
  548.  
  549.    key1 = keytab[ss->kind][0];
  550.    key2 = keytab[ss->kind][1];
  551.    four_way_startsetup = FALSE;
  552.  
  553.    if (key1 != b_nothing && key2 != b_nothing) {
  554.       if (key1 == key2) {     /* This is for things like 2x2 or 1x1. */
  555.          linedefinition = assoc(key1, ss, calldeflist);
  556.          coldefinition = linedefinition;
  557.          four_way_startsetup = TRUE;
  558.       }
  559.       else {
  560.          if (newtb & 010) linedefinition = assoc(key1, ss, calldeflist);
  561.          if (newtb & 1) coldefinition = assoc(key2, ss, calldeflist);
  562.       }
  563.    }
  564.  
  565.    switch (ss->kind) {
  566.       case s_short6:
  567.       case s_bone6:
  568.       case s_trngl:
  569.          break;
  570.       default:
  571.          if (final_concepts & FINAL__TRIANGLE)
  572.             fail("Triangle concept not allowed here.");
  573.    }
  574.  
  575.    /* If we found a definition for the setup we are in, we win.
  576.       This is true even if we only found a definition for the lines version
  577.       of the setup and not the columns version, or vice-versa.
  578.       If we need both and don't have both, we will lose. */
  579.  
  580.    if (linedefinition || coldefinition) {
  581.       /* Raise a warning if the "split" concept was explicitly used but the
  582.          call would have naturally split that way anyway. */
  583.  
  584. /* ******* we have patched this out, because we aren't convinced that it really
  585.    works.  How do we make it not complain on "split sidetrack" even though some
  586.    parts of the call, like the "zig-zag", would complain?  And how do we account
  587.    for the fact that it is observed not to raise the warning on split sidetrack
  588.    even though we don't understand why?  By the way, uncertainty about this is what
  589.    led us to make this a warning.  It was originally an error.  Which is correct?
  590.    It is probably best to leave it as a warning of the "don't use in resolve" type.
  591.  
  592.       if (ss->setupflags & SETUPFLAG__SAID_SPLIT) {
  593.          switch (ss->kind) {
  594.             case s2x2:
  595.                if (!assoc(b_2x4, ss, calldeflist) && !assoc(b_4x2, ss, calldeflist))
  596.                   warn(warn__excess_split);
  597.                break;
  598.             case s1x4:
  599.                if (!assoc(b_1x8, ss, calldeflist) && !assoc(b_8x1, ss, calldeflist))
  600.                   warn(warn__excess_split);
  601.                break;
  602.             case sdmd:
  603.                if (!assoc(b_qtag, ss, calldeflist) && !assoc(b_pqtag, ss, calldeflist) &&
  604.                         !assoc(b_ptpd, ss, calldeflist) && !assoc(b_pptpd, ss, calldeflist))
  605.                   warn(warn__excess_split);
  606.                break;
  607.          }
  608.       }
  609. */
  610.  
  611.       if (final_concepts & FINAL__TRIANGLE)
  612.          fail("Triangle concept not allowed here.");
  613.  
  614.       goto do_the_call;
  615.    }
  616.  
  617.    /* It looks as though we need to divide the setup.  It will be
  618.       helpful to have a mask of where the live people are. */
  619.  
  620.    for (i=0, j=1, livemask = 0; i<=setup_limits[ss->kind]; i++, j<<=1) {
  621.       if (ss->people[i].id1) livemask |= j;
  622.    }
  623.  
  624.    switch (ss->kind) {
  625.       case s4x4:
  626.          /* The only way this can be legal is if we can identify
  627.             smaller setups of all real people and can do the call on them.  For
  628.             example, if the outside phantom lines are fully occupied and the inside
  629.             ones empty, we could do a swing-thru.  We also identify Z's from which
  630.             we can do "Z axle". */
  631.    
  632.          switch (livemask) {
  633.             case 0x7171:
  634.                division_maps = &map_4x4_ns;
  635.                warn(warn__each1x4);
  636.                goto divide_us_no_recompute;
  637.             case 0x1717:
  638.                division_maps = &map_4x4_ew;
  639.                warn(warn__each1x4);
  640.                goto divide_us_no_recompute;
  641.             case 0x4E4E: case 0x8B8B:
  642.                division_maps = &map_rh_s2x3_3;
  643.                /* If this changes shape (as it will in the only known case
  644.                   of this -- Z axle), divided_setup_move will give a warning
  645.                   about going to a parallelogram, since we did not start
  646.                   with 50% offset, though common practice says that a
  647.                   parallelogram is the correct result.  If the call turns out
  648.                   not to be a shape-changer, no warning will be given.  If
  649.                   the call is a shape changer that tries to go into a setup
  650.                   other than a parallelogram, divided_setup_move will raise
  651.                   an error. */
  652.                ss->setupflags |= SETUPFLAG__OFFSET_Z;
  653.                if ((callspec->callflags & cflag__split_large_setups) &&
  654.                      (!(newtb & 010) || assoc(b_3x2, ss, calldeflist)) &&
  655.                      (!(newtb & 001) || assoc(b_2x3, ss, calldeflist)))
  656.                   goto divide_us_no_recompute;
  657.             case 0xA6A6: case 0x9C9C:
  658.                division_maps = &map_lh_s2x3_3;
  659.                ss->setupflags |= SETUPFLAG__OFFSET_Z;
  660.                if ((callspec->callflags & cflag__split_large_setups) &&
  661.                      (!(newtb & 010) || assoc(b_3x2, ss, calldeflist)) &&
  662.                      (!(newtb & 001) || assoc(b_2x3, ss, calldeflist)))
  663.                   goto divide_us_no_recompute;
  664.             case 0xE4E4: case 0xB8B8:
  665.                division_maps = &map_rh_s2x3_2;
  666.                ss->setupflags |= SETUPFLAG__OFFSET_Z;
  667.                if ((callspec->callflags & cflag__split_large_setups) &&
  668.                      (!(newtb & 010) || assoc(b_2x3, ss, calldeflist)) &&
  669.                      (!(newtb & 001) || assoc(b_3x2, ss, calldeflist)))
  670.                   goto divide_us_no_recompute;
  671.             case 0x6A6A: case 0xC9C9:
  672.                division_maps = &map_lh_s2x3_2;
  673.                ss->setupflags |= SETUPFLAG__OFFSET_Z;
  674.                if ((callspec->callflags & cflag__split_large_setups) &&
  675.                      (!(newtb & 010) || assoc(b_2x3, ss, calldeflist)) &&
  676.                      (!(newtb & 001) || assoc(b_3x2, ss, calldeflist)))
  677.                   goto divide_us_no_recompute;
  678.          }
  679.  
  680.          fail("You must specify a concept.");
  681.       case s2x6:
  682.          /* The call has no applicable 2x6 or 6x2 definition. */
  683.          /* First, check whether it has 2x3/3x2 definitions, and divide the setup if so,
  684.             and if the call permits it.  This is important for permitting "Z axle" from
  685.             a 2x6 but forbidding "circulate". */
  686.  
  687.          if ((callspec->callflags & cflag__split_large_setups) &&
  688.                   (!(newtb & 010) || assoc(b_2x3, ss, calldeflist)) &&
  689.                   (!(newtb & 001) || assoc(b_3x2, ss, calldeflist))) {
  690.             division_maps = (*map_lists[s_2x3][1])[MPKIND__SPLIT][0];
  691.             goto divide_us_no_recompute;
  692.          }
  693.    
  694.          /* Otherwise, the only way this can be legal is if we can identify
  695.             smaller setups of all real people and can do the call on them.  For
  696.             example, we will look for 1x4 setups, so we could do things like
  697.             swing thru from a parallelogram. */
  698.    
  699.          switch (livemask) {
  700.             case 07474:    /* a parallelogram */
  701.                division_maps = (*map_lists[s1x4][1])[MPKIND__OFFS_R_HALF][1];
  702.                warn(warn__each1x4);
  703.                goto divide_us_no_recompute;
  704.             case 01717:    /* a parallelogram */
  705.                division_maps = (*map_lists[s1x4][1])[MPKIND__OFFS_L_HALF][1];
  706.                warn(warn__each1x4);
  707.                goto divide_us_no_recompute;
  708.             case 06363:    /* the outer triple boxes */
  709.                division_maps = (*map_lists[s2x2][2])[MPKIND__SPLIT][0];
  710.                warn(warn__each2x2);
  711.                goto divide_us_no_recompute;
  712.          }
  713.    
  714.          fail("You must specify a concept.");
  715.       case s2x8:
  716.    
  717.          /* The only way this can be legal is if we can identify
  718.             smaller setups of all real people and can do the call on them.  For
  719.             example, we will look for 1x4 setups, so we could do things like
  720.             swing thru from a totally offset parallelogram. */
  721.    
  722.          switch (livemask) {
  723.             case 0xF0F0:    /* a parallelogram */
  724.                division_maps = (*map_lists[s1x4][1])[MPKIND__OFFS_R_FULL][1];
  725.                warn(warn__each1x4);
  726.                break;
  727.             case 0x0F0F:    /* a parallelogram */
  728.                division_maps = (*map_lists[s1x4][1])[MPKIND__OFFS_L_FULL][1];
  729.                warn(warn__each1x4);
  730.                break;
  731.             case 0xC3C3:    /* the outer quadruple boxes */
  732.                division_maps = (*map_lists[s2x2][3])[MPKIND__SPLIT][0];
  733.                warn(warn__each2x2);
  734.                break;
  735.             default:
  736.                fail("You must specify a concept.");
  737.          }
  738.    
  739.          goto divide_us_no_recompute;
  740.       case s_c1phan:
  741.    
  742.          /* The only way this can be legal is if people are in genuine
  743.             C1 phantom spots and the call can be done from 1x2's or 2x1's.
  744.             *** Actually, that isn't so.  We ought to be able to do 1x1 calls
  745.             from any population at all. */
  746.    
  747.          if ((livemask & 0xAAAA) == 0)
  748.             division_maps = (*map_lists[s_1x2][3])[MPKIND__4_QUADRANTS][0];
  749.          else if ((livemask & 0x5555) == 0)
  750.             division_maps = (*map_lists[s_1x2][3])[MPKIND__4_QUADRANTS][1];
  751.          else
  752.             fail("You must specify a concept.");
  753.    
  754.          goto divide_us_no_recompute;
  755.       case s2x2:
  756.          /* Any 2x2 -> 2x2 call that acts by dividing itself into 1x2's
  757.             is presumed to want the people in each 1x2 to stay near each other.
  758.             We signify that by reverting to the original elongation,
  759.             overriding anything that may have been in the call definition. */
  760.  
  761.          desired_elongation = orig_elongation;
  762.  
  763.          /* Tentatively choose a map.  We may change it later to "map_2x2v". */
  764.          division_maps = (*map_lists[s_1x2][1])[MPKIND__SPLIT][1];
  765.    
  766.          if ((newtb & 011) == 011) {
  767.             /* The situation is serious.  If the call has both 1x2 and 2x1 definitions,
  768.                we can do it, by guessing correctly which way to divide the setup.
  769.                Otherwise, if it has either a 1x2 or a 2x1 definition, but not both,
  770.                we lose, because the call presumably wants to use same.
  771.                But if the call has neither 1x2 nor 2x1 definitions, but does have
  772.                a 1x1 definition, we can do it.  Just divide the setup arbitrarily. */
  773.    
  774.             if (assoc(b_2x1, ss, calldeflist)) {
  775.                if (assoc(b_1x2, ss, calldeflist)) {
  776.                   /* The call has both definitions.  We look at the manner in
  777.                      which the setup is T-boned in order to figure out how
  778.                      to divide the setup. */
  779.    
  780.                   if ((((ss->people[0].id1 | ss->people[3].id1) & 011) != 011) &&
  781.                         (((ss->people[1].id1 | ss->people[2].id1) & 011) != 011))
  782.                      division_maps = &map_2x2v;
  783.                   else if ((((ss->people[0].id1 | ss->people[1].id1) & 011) == 011) ||
  784.                         (((ss->people[2].id1 | ss->people[3].id1) & 011) == 011))
  785.                      fail("Can't figure out who should be working with whom.");
  786.    
  787.                   goto divide_us_no_recompute;
  788.                }
  789.                else
  790.                   fail("People are not working with each other in a consistent way.");
  791.             }
  792.             else if (assoc(b_1x2, ss, calldeflist))
  793.                fail("People are not working with each other in a consistent way.");
  794.             else if (assoc(b_1x1, ss, calldeflist))
  795.                goto divide_us_no_recompute;
  796.          }
  797.          else {
  798.             /* People are not T-boned.  Check for a 2x1 or 1x2 definition.
  799.                If found, use it as a guide.  If both are present, we use
  800.                the setup elongation flag to tell us what to do.  In any
  801.                case, the setup elongation flag, if present, must not be
  802.                inconsistent with our decision. */
  803.  
  804.             unsigned long int elong = 0;
  805.  
  806.             if (assoc(b_2x1, ss, calldeflist)) {
  807.                elong |= (2 -  (newtb & 1));
  808.             }
  809.  
  810.             if (assoc(b_1x2, ss, calldeflist)) {
  811.                elong |= (1 + (newtb & 1));
  812.             }
  813.  
  814.             if (elong == 0) {
  815.                /* Neither 2x1 or 1x2 definition existed.  Check for 1x1.
  816.                   If found, any division axis will work. */
  817.                if (assoc(b_1x1, ss, calldeflist))
  818.                   goto divide_us_no_recompute;
  819.             }
  820.             else {
  821.                /* It's too bad switch statements can't take constants in their case values. */
  822.                unsigned long int foo = (ss->setupflags | ~(elong*SETUPFLAG__ELONGATE_BIT)) & SETUPFLAG__ELONGATE_MASK;
  823.  
  824.                if (foo == (2*SETUPFLAG__ELONGATE_BIT))
  825.                   goto divide_us_no_recompute;
  826.                else if (foo == (1*SETUPFLAG__ELONGATE_BIT)) {
  827.                   division_maps = &map_2x2v;
  828.                   goto divide_us_no_recompute;
  829.                }
  830.                else if (foo == 0) {
  831.                   fail("Can't figure out who should be working with whom.");
  832.                }
  833.                else
  834.                   fail("People are too far away to work with each other on this call.");
  835.             }
  836.          }
  837.  
  838.          break;
  839.       case s2x4:
  840.          division_maps = (*map_lists[s2x2][1])[MPKIND__SPLIT][0];    /* The map we will probably use. */
  841.    
  842.          /* See if this call is being done "split" as in "split square thru" or "split dixie style",
  843.             in which case split into boxes. */
  844.    
  845.          if (final_concepts & (FINAL__SPLIT_SQUARE_APPROVED | FINAL__SPLIT_DIXIE_APPROVED))
  846.             goto divide_us_no_recompute;
  847.    
  848.          /* See if this call has applicable 1x4 or 4x1 definitions, in which case split it that way. */
  849.       
  850.          else if ((!(newtb & 010) || assoc(b_1x4, ss, calldeflist)) &&
  851.                (!(newtb & 1) || assoc(b_4x1, ss, calldeflist))) {
  852.             division_maps = (*map_lists[s1x4][1])[MPKIND__SPLIT][1];
  853.             goto divide_us_no_recompute;
  854.          }
  855.    
  856.          /* See if this call has applicable 2x2 definition, in which case split into boxes. */
  857.             
  858.          else if (assoc(b_2x2, ss, calldeflist)) goto divide_us_no_recompute;
  859.    
  860.          /* See if this call has applicable 1x2 or 2x1 definitions, (but not 2x2), in non-T-boned setup.
  861.             If so, split into boxes. */
  862.    
  863.          else if (((newtb & 011) != 011) && (assoc(b_1x2, ss, calldeflist) || assoc(b_2x1, ss, calldeflist)))
  864.             goto divide_us_no_recompute;
  865.       
  866.          /* If we are T-boned and have 1x2 or 2x1 definitions, we need to be careful. */
  867.    
  868.          else if ((newtb & 011) == 011) {
  869.             int tbi = ss->people[1].id1 | ss->people[2].id1 | ss->people[5].id1 | ss->people[6].id1;
  870.             int tbo = ss->people[0].id1 | ss->people[3].id1 | ss->people[4].id1 | ss->people[7].id1;
  871.    
  872.             /* If the centers and ends are separately consistent, we can do the call concentrically *IF*
  873.                the appropriate type of definition exists for the ends to work with the near person rather
  874.                than the far one.  This is what makes "heads into the middle and everbody partner trade" work,
  875.                and forbids "heads into the middle and everbody star thru". */
  876.    
  877.             if (((tbi & 011) != 011) && ((tbo & 011) != 011)) {
  878.                if ((!(tbo & 010) || assoc(b_2x1, ss, calldeflist)) &&
  879.                         (!(tbo & 1) || assoc(b_1x2, ss, calldeflist))) {
  880.                   concentric_move(ss, parseptr, parseptr, callspec, callspec, final_concepts, final_concepts, schema_concentric, 0, 0, result);
  881.                   goto un_mirror;
  882.                }
  883.  
  884.                /* Or if we have a 1x1 definition, we can divide it.  Otherwise, we lose. */
  885.                else if (assoc(b_1x1, ss, calldeflist)) goto divide_us_no_recompute;
  886.             }
  887.    
  888.             /* If the centers and ends are not separately consistent, we should just split it into 2x2's.
  889.                Perhaps the call has both 1x2 and 2x1 definitions, and will be done sort of siamese in each quadrant.
  890.                Another possibility is that the call has just (say) 1x2 definitions, but everyone can do their
  891.                part and miraculously not hit each other. */
  892.    
  893.             else goto divide_us_no_recompute;
  894.          }
  895.    
  896.          /* We are not T-boned, and there is no 1x2 or 2x1 definition.  The only possibility is that there
  897.             is a 1x1 definition, in which case splitting into boxes will work. */
  898.    
  899.          else if (assoc(b_1x1, ss, calldeflist)) goto divide_us_no_recompute;
  900.          break;
  901.       case s_rigger:
  902.          {
  903.             int tinytb = ss->people[2].id1 | ss->people[3].id1 | ss->people[6].id1 | ss->people[7].id1;
  904.    
  905.             /* See if this call has applicable 1x2 or 2x1 definitions, and the people in the wings are
  906.                facing appropriately.  Then do it concentrically. */
  907.    
  908.             if ((!(tinytb & 010) || assoc(b_1x2, ss, calldeflist)) &&
  909.                (!(tinytb & 1) || assoc(b_2x1, ss, calldeflist))) {
  910.                concentric_move(ss, parseptr, parseptr, callspec, callspec, final_concepts, final_concepts, schema_concentric, 0, 0, result);
  911.                goto un_mirror;
  912.             }
  913.          }
  914.          break;
  915.       case s3x4:
  916.          {
  917.             long_boolean can_do_boxes;
  918.             setup sss;
  919.             long_boolean really_fudged;
  920.  
  921.             /* The call has no applicable 3x4 or 4x3 definition. */
  922.             /* First, check whether it has 2x3/3x2 definitions, and divide the setup if so,
  923.                and if the call permits it.  This is important for permitting "Z axle" from
  924.                a 3x4 but forbidding "circulate" (unless we give a concept like 12 matrix
  925.                phantom columns.) */
  926.       
  927.             if ((callspec->callflags & cflag__split_large_setups) &&
  928.                   (!(newtb & 010) || assoc(b_3x2, ss, calldeflist)) &&
  929.                   (!(newtb & 001) || assoc(b_2x3, ss, calldeflist))) {
  930.                division_maps = (*map_lists[s_2x3][1])[MPKIND__SPLIT][1];
  931.                goto divide_us_no_recompute;
  932.             }
  933.    
  934.             /* Either we are actually in an offset lines/columns situation and the call has
  935.                a definition for 2x2 but not bigger things, in which case we give a warning,
  936.                remove the offset (turning it into a 2x4) and do the call, or the setup can
  937.                be fudged into a quarter-tag and we can do such a call.  We do not allow the offset
  938.                removal if the call has a definition from a 2x4, for example, so that we can't
  939.                say "circulate" from offset waves (do we mean each box? do we mean 12 matrix?)
  940.                but we can say "cross back", a call which presumably will be perceived as unambiguous. */
  941.                
  942.             /* See if this call has applicable 2x2 definition, but not 2x3/3x2/2x4/4x2, in which case
  943.                try to make an offset 2x4, which will cause the call to be done in each 2x2. */
  944.       
  945.             can_do_boxes =
  946.                   (
  947.                         assoc(b_2x2, ss, calldeflist) ||
  948.                         assoc(b_1x2, ss, calldeflist) ||
  949.                         assoc(b_2x1, ss, calldeflist) ||
  950.                         assoc(b_1x1, ss, calldeflist)) &&
  951.                   (!assoc(b_2x4, ss, calldeflist)) &&
  952.                   (!assoc(b_4x2, ss, calldeflist)) &&
  953.                   (!assoc(b_2x3, ss, calldeflist)) &&
  954.                   (!assoc(b_3x2, ss, calldeflist)) &&
  955.                   (!assoc(b_dmd, ss, calldeflist)) &&
  956.                   (!assoc(b_pmd, ss, calldeflist)) &&
  957.                   (!assoc(b_qtag, ss, calldeflist)) &&
  958.                   (!assoc(b_pqtag, ss, calldeflist));
  959.       
  960.             /* See if offset lines/columns spots are occupied.  If so, the quarter-tag fudge would not
  961.                work.  The only thing to do is check for the legality of 2x2 division and then remove the offset. */
  962.       
  963.             switch (livemask) {
  964.                case 07474:
  965.                   if (!can_do_boxes) fail("Don't know how to do this call in this setup.");
  966.                   warn(warn__each2x2);
  967.                   division_maps = (*map_lists[s2x2][1])[MPKIND__OFFS_L_HALF][0];
  968.                   goto divide_us_no_recompute;
  969.                case 06363:
  970.                   if (!can_do_boxes) fail("Don't know how to do this call in this setup.");
  971.                   warn(warn__each2x2);
  972.                   division_maps = (*map_lists[s2x2][1])[MPKIND__OFFS_R_HALF][0];
  973.                   goto divide_us_no_recompute;
  974.             }
  975.    
  976.             /* Now check for something that can be fudged into a "quarter tag"
  977.                (which includes diamonds).  Note whether we fudged,
  978.                since some calls do not tolerate it. */
  979.    
  980.             really_fudged = FALSE;
  981.    
  982.             (void) copy_person(&sss, 0, ss, 1);
  983.             (void) copy_person(&sss, 1, ss, 2);
  984.             (void) copy_person(&sss, 2, ss, 4);
  985.             (void) copy_person(&sss, 3, ss, 5);
  986.             (void) copy_person(&sss, 4, ss, 7);
  987.             (void) copy_person(&sss, 5, ss, 8);
  988.             (void) copy_person(&sss, 6, ss, 10);
  989.             (void) copy_person(&sss, 7, ss, 11);
  990.  
  991.             if (ss->people[0].id1) {
  992.                if (ss->people[1].id1) fail("Can't do this call from arbitrary 3x4 setup.");
  993.                else (void) copy_person(&sss, 0, ss, 0);
  994.                really_fudged = TRUE;
  995.             }
  996.             if (ss->people[3].id1) {
  997.                if (ss->people[2].id1) fail("Can't do this call from arbitrary 3x4 setup.");
  998.                else (void) copy_person(&sss, 1, ss, 3);
  999.                really_fudged = TRUE;
  1000.             }
  1001.             if (ss->people[6].id1) {
  1002.                if (ss->people[7].id1) fail("Can't do this call from arbitrary 3x4 setup.");
  1003.                else (void) copy_person(&sss, 4, ss, 6);
  1004.                really_fudged = TRUE;
  1005.             }
  1006.             if (ss->people[9].id1) {
  1007.                if (ss->people[8].id1) fail("Can't do this call from arbitrary 3x4 setup.");
  1008.                else (void) copy_person(&sss, 5, ss, 9);
  1009.                really_fudged = TRUE;
  1010.             }
  1011.          
  1012.             sss.kind = s_qtag;
  1013.             sss.rotation = ss->rotation;
  1014.             sss.setupflags = ss->setupflags | SETUPFLAG__DISTORTED;
  1015.             move(&sss, parseptr, callspec, final_concepts, really_fudged, result);
  1016.          }
  1017.  
  1018.          goto un_mirror;
  1019.       case s_qtag:
  1020.          if (assoc(b_dmd, ss, calldeflist) || assoc(b_pmd, ss, calldeflist)) {
  1021.             division_maps = (*map_lists[sdmd][1])[MPKIND__SPLIT][1];
  1022.             goto divide_us_no_recompute;
  1023.          }
  1024.          else if ((!(newtb & 010) || assoc(b_1x2, ss, calldeflist)) &&
  1025.                   (!(newtb & 1) || assoc(b_2x1, ss, calldeflist))) {
  1026.             concentric_move(ss, parseptr, parseptr, callspec, callspec, final_concepts, final_concepts, schema_concentric, 0, 0, result);
  1027.             goto un_mirror;
  1028.          }
  1029.          break;
  1030.       case s_bone:
  1031.          {
  1032.             int tbi = ss->people[2].id1 | ss->people[3].id1 | ss->people[6].id1 | ss->people[7].id1;
  1033.             int tbo = ss->people[0].id1 | ss->people[1].id1 | ss->people[4].id1 | ss->people[5].id1;
  1034.  
  1035.             if ((!((tbi & 010) | (tbo & 001)) || assoc(b_1x2, ss, calldeflist)) &&
  1036.                      (!((tbi & 001) | (tbo & 010)) || assoc(b_2x1, ss, calldeflist))) {
  1037.                concentric_move(ss, parseptr, parseptr, callspec, callspec, final_concepts, final_concepts, schema_concentric, 0, 0, result);
  1038.                goto un_mirror;
  1039.             }
  1040.          }
  1041.          break;
  1042.       case s_ptpd:
  1043.          if (assoc(b_dmd, ss, calldeflist) || assoc(b_pmd, ss, calldeflist)) {
  1044.             division_maps = (*map_lists[sdmd][1])[MPKIND__SPLIT][0];
  1045.             goto divide_us_no_recompute;
  1046.          }
  1047.          break;
  1048.       case s_2x3:
  1049.          /* See if this call has applicable 1x2 or 2x1 definitions, in which case split it 3 ways. */
  1050.             
  1051.          if (assoc(b_1x2, ss, calldeflist) || assoc(b_2x1, ss, calldeflist) || assoc(b_1x1, ss, calldeflist)) {
  1052.             division_maps = (*map_lists[s_1x2][2])[MPKIND__SPLIT][1];
  1053.             goto divide_us_no_recompute;
  1054.          }
  1055.          break;
  1056.       case s_short6:
  1057.          if (assoc(b_trngl, ss, calldeflist) || assoc(b_ptrngl, ss, calldeflist) ||
  1058.                assoc(b_1x1, ss, calldeflist) || assoc(b_2x2, ss, calldeflist)) {
  1059.             division_maps = &map_s6_trngl;
  1060.             goto divide_us_no_recompute;
  1061.          }
  1062.          break;
  1063.       case s_bone6:
  1064.          if (assoc(b_trngl, ss, calldeflist) || assoc(b_ptrngl, ss, calldeflist) ||
  1065.                assoc(b_1x1, ss, calldeflist) || assoc(b_2x2, ss, calldeflist)) {
  1066.             division_maps = &map_b6_trngl;
  1067.             goto divide_us_no_recompute;
  1068.          }
  1069.          break;
  1070.       case s_trngl:
  1071.          if (assoc(b_2x2, ss, calldeflist)) {
  1072.             if (ss->setupflags & SETUPFLAG__SAID_TRIANGLE) {
  1073.                if (final_concepts & FINAL__TRIANGLE)
  1074.                   fail("'Triangle' concept is redundant.");
  1075.             }
  1076.             else {
  1077.                if (!(final_concepts & FINAL__TRIANGLE))
  1078.                   fail("You must give the 'triangle' concept.");
  1079.             }
  1080.  
  1081.             if ((ss->people[0].id1 & d_mask) == d_east)
  1082.                division_maps = &map_trngl_box1;
  1083.             else if ((ss->people[0].id1 & d_mask) == d_west)
  1084.                division_maps = &map_trngl_box2;
  1085.             else
  1086.                fail("Can't figure out which way triangle point is facing.");
  1087.  
  1088.             final_concepts &= ~FINAL__TRIANGLE;
  1089.             divided_setup_move(ss, parseptr, callspec, final_concepts, division_maps, phantest_ok, FALSE, result);
  1090.  
  1091.             switch (result->kind) {
  1092.                int rot;
  1093.  
  1094.                case s1x4:
  1095.                   if (result->people[0].id1 && !result->people[2].id1) {
  1096.                      (void) copy_person(result, 2, result, 3);
  1097.                   }
  1098.                   else if (result->people[2].id1 && !result->people[0].id1) {
  1099.                      (void) copy_person(result, 0, result, 1);
  1100.                      (void) copy_person(result, 1, result, 3);
  1101.                   }
  1102.                   else
  1103.                      fail("Bad ending setup for triangle-become-box.");
  1104.                   result->kind = s_1x3;
  1105.                   break;
  1106.                case s2x2:
  1107.                   if      (!result->people[0].id1) rot = 3;
  1108.                   else if (!result->people[1].id1) rot = 2;
  1109.                   else if (!result->people[2].id1) rot = 1;
  1110.                   else if (!result->people[3].id1) rot = 0;
  1111.                   else
  1112.                      fail("Bad ending setup for triangle-become-box.");
  1113.  
  1114.                   result->rotation += rot;
  1115.                   canonicalize_rotation(result);
  1116.                   /* Now the empty spot is in the lower-left corner. */
  1117.                   if ((!result->people[0].id1) || (!result->people[1].id1) || (!result->people[2].id1))
  1118.                      fail("Bad ending setup for triangle-become-box.");
  1119.  
  1120.                   if (result->people[0].id1 & result->people[2].id1 & 1) {
  1121.                      (void) copy_person(result, 3, result, 2);
  1122.                   }
  1123.                   else if (result->people[0].id1 & result->people[2].id1 & 010) {
  1124.                      rot--;
  1125.                      result->rotation--;
  1126.                      canonicalize_rotation(result);
  1127.                   }
  1128.                   else
  1129.                      fail("Bad ending setup for triangle-become-box.");
  1130.  
  1131.                   (void) copy_person(result, 2, result, 1);
  1132.                   (void) copy_person(result, 1, result, 0);
  1133.                   (void) copy_person(result, 0, result, 3);
  1134.                   result->kind = s_trngl;
  1135.                   result->rotation -= rot;   /* Put it back. */
  1136.                   canonicalize_rotation(result);
  1137.                   break;
  1138.                case sdmd:
  1139.                   if (result->people[0].id1 && !result->people[2].id1) {
  1140.                      (void) copy_rot(result, 2, result, 3, 033);
  1141.                      (void) copy_rot(result, 0, result, 0, 033);
  1142.                      (void) copy_rot(result, 1, result, 1, 033);
  1143.                      result->rotation++;
  1144.                   }
  1145.                   else if (result->people[2].id1 && !result->people[0].id1) {
  1146.                      (void) copy_rot(result, 0, result, 2, 011);
  1147.                      (void) copy_rot(result, 2, result, 1, 011);
  1148.                      (void) copy_rot(result, 1, result, 3, 011);
  1149.                      result->rotation--;
  1150.                   }
  1151.                   else
  1152.                      fail("Bad ending setup for triangle-become-box.");
  1153.                   result->kind = s_trngl;
  1154.                   break;
  1155.                default:
  1156.                   fail("Bad ending setup for triangle-become-box.");
  1157.             }
  1158.  
  1159.             goto un_mirror;
  1160.          }
  1161.          break;
  1162.       case s_1x6:
  1163.          /* See if this call has applicable 1x2 or 2x1 definitions, in which case split it 3 ways. */
  1164.             
  1165.          if (assoc(b_1x2, ss, calldeflist) || assoc(b_2x1, ss, calldeflist) || assoc(b_1x1, ss, calldeflist)) {
  1166.             division_maps = (*map_lists[s_1x2][2])[MPKIND__SPLIT][0];
  1167.             goto divide_us_no_recompute;
  1168.          }
  1169.          break;
  1170.       case s_1x2:
  1171.          if (assoc(b_1x1, ss, calldeflist)) {
  1172.             division_maps = (*map_lists[s_1x1][1])[MPKIND__SPLIT][0];
  1173.             goto divide_us_no_recompute;
  1174.          }
  1175.          break;
  1176.       case s1x8:
  1177.          /* See if the call has a 1x4, 4x1, 1x2, 2x1, or 1x1 definition, in which case split it and do each part. */
  1178.          
  1179.          if (    (assoc(b_1x4, ss, calldeflist) || assoc(b_4x1, ss, calldeflist) ||
  1180.                   assoc(b_1x2, ss, calldeflist) || assoc(b_2x1, ss, calldeflist) ||
  1181.                   assoc(b_1x1, ss, calldeflist))) {
  1182.             division_maps = (*map_lists[s1x4][1])[MPKIND__SPLIT][0];
  1183.             goto divide_us_no_recompute;
  1184.          }
  1185.          break;
  1186.       case s1x4:
  1187.          /* See if the call has a 1x2, 2x1, or 1x1 definition, in which case split it and do each part. */
  1188.          
  1189.          if ((assoc(b_1x2, ss, calldeflist) || assoc(b_2x1, ss, calldeflist) || assoc(b_1x1, ss, calldeflist))) {
  1190.  
  1191.             /* The following makes "ends hinge" work from a grand wave.  Any 1x4 -> 2x2 call
  1192.                that acts by dividing itself into 1x2's is presumed to want the people in each 1x2
  1193.                to stay near each other.  We signify that by flipping the elongation, which we
  1194.                had previously set perpendicular to the 1x4 axis, overriding anything that may
  1195.                have been in the call definition. */
  1196.  
  1197.             desired_elongation = orig_elongation ^ RESULTFLAG__ELONGATE_MASK;
  1198.             /* If the flags were zero and we complemented them so that both are set, that's not good. */
  1199.             if (desired_elongation == RESULTFLAG__ELONGATE_MASK)
  1200.                desired_elongation = 0;
  1201.  
  1202.             division_maps = (*map_lists[s_1x2][1])[MPKIND__SPLIT][0];
  1203.             goto divide_us_no_recompute;
  1204.          }
  1205.          break;
  1206.    }
  1207.  
  1208.    /* We are about to do the call by array! */
  1209.  
  1210.    do_the_call:
  1211.  
  1212.    funny = final_concepts & FINAL__FUNNY;
  1213.    inconsistent_rotation = 0;
  1214.  
  1215.    if (funny && (!(calldeflist->callarray_flags & CAF__FACING_FUNNY)))
  1216.       fail("Can't do this call 'funny'.");
  1217.  
  1218.    /* Check that "linedefinition" has been set up if we will need it. */
  1219.    
  1220.    goodies = (callarray *) 0;
  1221.  
  1222.    if ((newtb & 010) || four_way_startsetup) {
  1223.       if (!linedefinition) {
  1224.          switch (ss->kind) {
  1225.             case sdmd:
  1226.                fail("Can't handle people in diamond or PU quarter-tag for this call.");
  1227.             case s_trngl:
  1228.                fail("Can't handle people in triangle for this call.");
  1229.             case s_qtag:
  1230.                fail("Can't handle people in quarter tag for this call.");
  1231.             case s3x4:
  1232.                fail("Can't handle people in triple lines for this call.");
  1233.             case s_2x3: case s2x4:
  1234.                fail("Can't handle people in lines for this call.");
  1235.             case s_short6:
  1236.                fail("Can't handle people in tall/short 6 for this call.");
  1237.             case s2x2:
  1238.                fail("Can't handle people in box of 4 for this call.");
  1239.             case s_1x2:
  1240.                fail("Can't handle people in line of 2 for this call.");
  1241.             case s1x4:
  1242.                fail("Can't handle people in line of 4 for this call.");
  1243.             case s_1x6:
  1244.                fail("Can't handle people in line of 6 for this call.");
  1245.             case s1x8:
  1246.                fail("Can't handle people in line of 8 for this call.");
  1247.             case s_galaxy:
  1248.                fail("Can't handle people in galaxy for this call.");
  1249.             default:
  1250.                fail("Can't do this call.");
  1251.          }
  1252.       }
  1253.    
  1254.       ldef = linedefinition;
  1255.       goodies = ldef;
  1256.  
  1257.       if (ldef->restriction == cr_alwaysfail) goto ldef_failed;
  1258.  
  1259.       switch (ss->kind) {
  1260.          int t, q0, q1, q2, q3, q4, q5, q6, q7;
  1261.  
  1262.          case s2x2:
  1263.             switch (ldef->restriction) {
  1264.                case cr_wave_only:
  1265.                   /* check for a "real" (walk-and-dodge type) box */
  1266.                   k = 0; j = 0; i = 3; z = 3;
  1267.                   if (t = ss->people[0].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1268.                   if (t = ss->people[1].id1) { j |= t; i &= t; k |= (t^2); z &= (t^2); }
  1269.                   if (t = ss->people[2].id1) { j |= t; z &= t; k |= (t^2); i &= (t^2); }
  1270.                   if (t = ss->people[3].id1) { k |= t; z &= t; j |= (t^2); i &= (t^2); }
  1271.                   if ((k&3) && ((~i)&3) && (j&3) && ((~z)&3))
  1272.                      goto ldef_failed;
  1273.                   break;
  1274.                case cr_2fl_only:
  1275.                   /* check for a "one-faced" (reverse-the-pass type) box */
  1276.                   k = 0; j = 0; i = 3; z = 3;
  1277.                   if (t = ss->people[0].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1278.                   if (t = ss->people[1].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1279.                   if (t = ss->people[2].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1280.                   if (t = ss->people[3].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1281.                   if ((k&3) && ((~i)&3) && (j&3) && ((~z)&3))
  1282.                      goto ldef_failed;
  1283.                   break;
  1284.                case cr_magic_only:
  1285.                   /* check for a "magic" (split-trade-circulate type) box */
  1286.                   k = 0; j = 0; i = 3; z = 3;
  1287.                   if (t = ss->people[0].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1288.                   if (t = ss->people[1].id1) { j |= t; z &= t; k |= (t^2); i &= (t^2); }
  1289.                   if (t = ss->people[2].id1) { k |= t; i &= t; j |= (t^2); z &= (t^2); }
  1290.                   if (t = ss->people[3].id1) { j |= t; z &= t; k |= (t^2); i &= (t^2); }
  1291.                   if ((k&3) && ((~i)&3) && (j&3) && ((~z)&3))
  1292.                      goto ldef_failed;
  1293.                   break;
  1294.                case cr_couples_only:
  1295.                   /* check for everyone as a couple */
  1296.                   q0 = 0; q1 = 0; q2 = 3; q3 = 3;
  1297.                   q4 = 0; q5 = 0; q7 = 3; q6 = 3;
  1298.                   if (t = ss->people[0].id1) { q0 |= t; q2 &= t; q1 |= (t^2); q3 &= (t^2); }
  1299.                   if (t = ss->people[1].id1) { q0 |= t; q7 &= t; q1 |= (t^2); q6 &= (t^2); }
  1300.                   if (t = ss->people[2].id1) { q5 |= t; q7 &= t; q4 |= (t^2); q6 &= (t^2); }
  1301.                   if (t = ss->people[3].id1) { q5 |= t; q2 &= t; q4 |= (t^2); q3 &= (t^2); }
  1302.                   if (((q0&3) && ((~q2)&3) && (q1&3) && ((~q3)&3)) ||
  1303.                       ((q5&3) && ((~q7)&3) && (q4&3) && ((~q6)&3)))
  1304.                      goto ldef_failed;
  1305.                   break;
  1306.                case cr_peelable_box:
  1307.                   /* check for a "peelable" (everyone in genuine tandem somehow) box */
  1308.                   q0 = 0; q1 = 0; q2 = 3; q3 = 3;
  1309.                   q4 = 0; q5 = 0; q7 = 3; q6 = 3;
  1310.                   if (t = ss->people[0].id1) { q0 |= t; q2 &= t; q1 |= (t^2); q3 &= (t^2); }
  1311.                   if (t = ss->people[1].id1) { q5 |= t; q2 &= t; q4 |= (t^2); q3 &= (t^2); }
  1312.                   if (t = ss->people[2].id1) { q5 |= t; q7 &= t; q4 |= (t^2); q6 &= (t^2); }
  1313.                   if (t = ss->people[3].id1) { q0 |= t; q7 &= t; q1 |= (t^2); q6 &= (t^2); }
  1314.                   if (((q0&3) && ((~q2)&3) && (q1&3) && ((~q3)&3)) ||
  1315.                       ((q5&3) && ((~q7)&3) && (q4&3) && ((~q6)&3)))
  1316.                      goto ldef_failed;
  1317.                   break;
  1318.                case cr_not_tboned:
  1319.                   /* check for a box that is not T-boned */
  1320.                   if (((ss->people[0].id1 | ss->people[1].id1 | ss->people[2].id1 | ss->people[3].id1) & 011) == 011)
  1321.                      goto ldef_failed;
  1322.                   break;
  1323.             }
  1324.             break;
  1325.          case s2x4:
  1326.             switch (ldef->restriction) {
  1327.                case cr_wave_only:
  1328.                   k = 0;         /* check for parallel waves */
  1329.                   i = 2;
  1330.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1331.                   if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1332.                   if (t = ss->people[2].id1) { k |=  t; i &=  t; }
  1333.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1334.                   if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1335.                   if (t = ss->people[5].id1) { k |=  t; i &=  t; }
  1336.                   if (t = ss->people[6].id1) { k |= ~t; i &= ~t; }
  1337.                   if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1338.                   if (k & ~i & 2)
  1339.                      goto ldef_failed;
  1340.                   break;
  1341.                case cr_1fl_only:
  1342.                   q0 = 0; q1 = 0; /* check for parallel one-faced lines */
  1343.                   q2 = 0; q3 = 0;
  1344.                   if (t = ss->people[0].id1) { q0 |= t; q1 |= ~t; }
  1345.                   if (t = ss->people[1].id1) { q0 |= t; q1 |= ~t; }
  1346.                   if (t = ss->people[2].id1) { q0 |= t; q1 |= ~t; }
  1347.                   if (t = ss->people[3].id1) { q0 |= t; q1 |= ~t; }
  1348.                   if (t = ss->people[4].id1) { q2 |= t; q3 |= ~t; }
  1349.                   if (t = ss->people[5].id1) { q2 |= t; q3 |= ~t; }
  1350.                   if (t = ss->people[6].id1) { q2 |= t; q3 |= ~t; }
  1351.                   if (t = ss->people[7].id1) { q2 |= t; q3 |= ~t; }
  1352.                   if (((q0&q1&2)) || ((q2&q3&2)))
  1353.                      goto ldef_failed;
  1354.                   break;
  1355.                case cr_2fl_only:
  1356.                   k = 0;         /* check for parallel two-faced lines */
  1357.                   i = 2;
  1358.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1359.                   if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1360.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1361.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1362.                   if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1363.                   if (t = ss->people[5].id1) { k |= ~t; i &= ~t; }
  1364.                   if (t = ss->people[6].id1) { k |=  t; i &=  t; }
  1365.                   if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1366.                   if (k & ~i & 2)
  1367.                      goto ldef_failed;
  1368.                   break;
  1369.                case cr_peelable_box:
  1370.                   /* check for ends in a "peelable" (everyone in genuine tandem somehow) box */
  1371.                   q1 = 0; q0 = 0; q5 = 0; q4 = 0;
  1372.                   if (t = ss->people[0].id1) { q1 |= t; q0 |= (t^2); }
  1373.                   if (t = ss->people[3].id1) { q5 |= t; q4 |= (t^2); }
  1374.                   if (t = ss->people[4].id1) { q5 |= t; q4 |= (t^2); }
  1375.                   if (t = ss->people[7].id1) { q1 |= t; q0 |= (t^2); }
  1376.                   if (((q1&3) && (q0&3)) || ((q5&3) && (q4&3)))
  1377.                      goto ldef_failed;
  1378.                   break;
  1379.                case cr_couples_only:
  1380.                   /* check for everyone as a couple */
  1381.                   q0 = 0; q1 = 0;
  1382.                   q4 = 0; q5 = 0;
  1383.                   q2 = 0; q3 = 0;
  1384.                   q6 = 0; q7 = 0;
  1385.                   if (t = ss->people[0].id1) { q0 |= t; q1 |= (t^2); }
  1386.                   if (t = ss->people[1].id1) { q0 |= t; q1 |= (t^2); }
  1387.                   if (t = ss->people[2].id1) { q5 |= t; q4 |= (t^2); }
  1388.                   if (t = ss->people[3].id1) { q5 |= t; q4 |= (t^2); }
  1389.                   if (t = ss->people[4].id1) { q2 |= t; q3 |= (t^2); }
  1390.                   if (t = ss->people[5].id1) { q2 |= t; q3 |= (t^2); }
  1391.                   if (t = ss->people[6].id1) { q6 |= t; q7 |= (t^2); }
  1392.                   if (t = ss->people[7].id1) { q6 |= t; q7 |= (t^2); }
  1393.                   if (((q0&3) && (q1&3)) ||
  1394.                       ((q2&3) && (q3&3)) ||
  1395.                       ((q6&3) && (q7&3)) ||
  1396.                       ((q5&3) && (q4&3)))
  1397.                      goto ldef_failed;
  1398.                   break;
  1399.             }
  1400.             break;
  1401.          case s_2x3:
  1402.             switch (ldef->restriction) {
  1403.                case cr_1fl_only:
  1404.                   q0 = 0; q1 = 0; /* check for parallel one-faced lines of 3 */
  1405.                   q2 = 0; q3 = 0;
  1406.                   if (t = ss->people[0].id1) { q0 |= t; q1 |= ~t; }
  1407.                   if (t = ss->people[1].id1) { q0 |= t; q1 |= ~t; }
  1408.                   if (t = ss->people[2].id1) { q0 |= t; q1 |= ~t; }
  1409.                   if (t = ss->people[3].id1) { q2 |= t; q3 |= ~t; }
  1410.                   if (t = ss->people[4].id1) { q2 |= t; q3 |= ~t; }
  1411.                   if (t = ss->people[5].id1) { q2 |= t; q3 |= ~t; }
  1412.                   if (((q0&q1&2)) || ((q2&q3&2)))
  1413.                      goto ldef_failed;
  1414.                   break;
  1415.             }
  1416.             break;
  1417.          case s_qtag:
  1418.             switch (ldef->restriction) {
  1419.                case cr_wave_only:
  1420.                   k = 0;         /* check for wave across the center */
  1421.                   i = 2;
  1422.                   if (t = ss->people[2].id1) { k |=  t; i &=  t; }
  1423.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1424.                   if (t = ss->people[6].id1) { k |= ~t; i &= ~t; }
  1425.                   if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1426.                   if (k & ~i & 2)
  1427.                      goto ldef_failed;
  1428.                   break;
  1429.                case cr_2fl_only:
  1430.                   k = 0;         /* check for two-faced line across the center */
  1431.                   i = 2;
  1432.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1433.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1434.                   if (t = ss->people[6].id1) { k |=  t; i &=  t; }
  1435.                   if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1436.                   if (k & ~i & 2)
  1437.                      goto ldef_failed;
  1438.                   break;
  1439.             }
  1440.             break;
  1441.          case s1x8:
  1442.             switch (ldef->restriction) {
  1443.                case cr_wave_only:
  1444.                   k = 0;         /* check for grand wave */
  1445.                   i = 2;
  1446.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1447.                   if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1448.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1449.                   if (t = ss->people[3].id1) { k |=  t; i &=  t; }
  1450.                   if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1451.                   if (t = ss->people[5].id1) { k |=  t; i &=  t; }
  1452.                   if (t = ss->people[6].id1) { k |=  t; i &=  t; }
  1453.                   if (t = ss->people[7].id1) { k |= ~t; i &= ~t; }
  1454.                   if (k & ~i & 2)
  1455.                      goto ldef_failed;
  1456.                   break;
  1457.                case cr_2fl_only:
  1458.                   k = 0;         /* check for grand two-faced line */
  1459.                   i = 2;
  1460.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1461.                   if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1462.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1463.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1464.                   if (t = ss->people[4].id1) { k |= ~t; i &= ~t; }
  1465.                   if (t = ss->people[5].id1) { k |= ~t; i &= ~t; }
  1466.                   if (t = ss->people[6].id1) { k |=  t; i &=  t; }
  1467.                   if (t = ss->people[7].id1) { k |=  t; i &=  t; }
  1468.                   if (k & ~i & 2)
  1469.                      goto ldef_failed;
  1470.                   break;
  1471.             }
  1472.             break;
  1473.          case s1x4:
  1474.             switch (ldef->restriction) {
  1475.                case cr_wave_only:
  1476.                   k = 0;         /* check for a wave */
  1477.                   i = 2;
  1478.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1479.                   if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1480.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1481.                   if (t = ss->people[3].id1) { k |=  t; i &=  t; }
  1482.                   if (k & ~i & 2)
  1483.                      goto ldef_failed;
  1484.                   break;
  1485.                case cr_2fl_only:
  1486.                   k = 0;         /* check for a 2-faced line */
  1487.                   i = 2;
  1488.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1489.                   if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1490.                   if (t = ss->people[2].id1) { k |= ~t; i &= ~t; }
  1491.                   if (t = ss->people[3].id1) { k |= ~t; i &= ~t; }
  1492.                   if (k & ~i & 2)
  1493.                      goto ldef_failed;
  1494.                   break;
  1495.                case cr_1fl_only:
  1496.                   k = 0;         /* check for a 1-faced line */
  1497.                   i = 0;
  1498.                   if (t = ss->people[0].id1) { k |= t; i |= ~t; }
  1499.                   if (t = ss->people[1].id1) { k |= t; i |= ~t; }
  1500.                   if (t = ss->people[2].id1) { k |= t; i |= ~t; }
  1501.                   if (t = ss->people[3].id1) { k |= t; i |= ~t; }
  1502.                   if (k & i & 2)
  1503.                      goto ldef_failed;
  1504.                   break;
  1505.                case cr_couples_only:
  1506.                   /* check for everyone as a couple */
  1507.                   q0 = 0; q1 = 0; q2 = 0; q3 = 0;
  1508.                   if (t = ss->people[0].id1) { q0 |= t; q1 |= ~t; }
  1509.                   if (t = ss->people[1].id1) { q0 |= t; q1 |= ~t; }
  1510.                   if (t = ss->people[2].id1) { q2 |= t; q3 |= ~t; }
  1511.                   if (t = ss->people[3].id1) { q2 |= t; q3 |= ~t; }
  1512.                   if (((q0&q1&2)) || ((q2&q3&2)))
  1513.                      goto ldef_failed;
  1514.                   break;
  1515.                case cr_awkward_centers:
  1516.                   k = 2;         /* check for centers not having left hands */
  1517.                   i = 2;
  1518.                   if (t = ss->people[1].id1) k &= ~t;
  1519.                   if (t = ss->people[3].id1) i &= t;
  1520.                   if (!((k | i) & 2)) warn(warn__awkward_centers);
  1521.                   break;
  1522.             }
  1523.             break;
  1524.          case s_1x2:
  1525.             switch (ldef->restriction) {
  1526.                case cr_wave_only:
  1527.                   k = 0;         /* check for a miniwave */
  1528.                   i = 2;
  1529.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1530.                   if (t = ss->people[1].id1) { k |= ~t; i &= ~t; }
  1531.                   if (k & ~i & 2)
  1532.                      goto ldef_failed;
  1533.                   break;
  1534.                case cr_2fl_only: case cr_couples_only:
  1535.                   k = 0;         /* check for a couple */
  1536.                   i = 2;
  1537.                   if (t = ss->people[0].id1) { k |=  t; i &=  t; }
  1538.                   if (t = ss->people[1].id1) { k |=  t; i &=  t; }
  1539.                   if (k & ~i & 2)
  1540.                      goto ldef_failed;
  1541.                   break;
  1542.                case cr_awkward_centers:
  1543.                   k = 2;         /* check for people not having left hands */
  1544.                   i = 2;
  1545.                   if (t = ss->people[0].id1) k &= ~t;
  1546.                   if (t = ss->people[1].id1) i &= t;
  1547.                   if (!((k | i) & 2)) warn(warn__awkward_centers);
  1548.                   break;
  1549.             }
  1550.             break;
  1551.       }
  1552.  
  1553.       goto ldef_won;
  1554.  
  1555.       ldef_failed:
  1556.  
  1557.       if (ldef->callarray_flags & CAF__RESTR_UNUSUAL) warn(warn__unusual);
  1558.       else if (ldef->callarray_flags & CAF__RESTR_FORBID) fail("This call is not legal from this formation.");
  1559.       else warn(warn__do_your_part);
  1560.  
  1561.       ldef_won: ;
  1562.    }
  1563.    
  1564.    /* Check that "coldefinition" has been set up if we will need it. */
  1565.    
  1566.    if ((newtb & 1) && (!four_way_startsetup)) {
  1567.       if (!coldefinition) {
  1568.          switch (ss->kind) {
  1569.             case sdmd:
  1570.                fail("Can't handle people in diamond or normal quarter-tag for this call.");
  1571.             case s_trngl:
  1572.                fail("Can't handle people in triangle for this call.");
  1573.             case s_qtag: case s3x4:
  1574.                fail("Can't handle people in triple columns for this call.");
  1575.             case s_2x3: case s2x4:
  1576.                fail("Can't handle people in columns for this call.");
  1577.             case s_short6:
  1578.                fail("Can't handle people in tall/short 6 for this call.");
  1579.             case s_1x2:
  1580.                fail("Can't handle people in column of 2 for this call.");
  1581.             case s1x4:
  1582.                fail("Can't handle people in column of 4 for this call.");
  1583.             case s_1x6:
  1584.                fail("Can't handle people in column of 6 for this call.");
  1585.             case s1x8:
  1586.                fail("Can't handle people in column of 8 for this call.");
  1587.             case s_galaxy:
  1588.                fail("Can't handle people in galaxy for this call.");
  1589.             default:
  1590.                fail("Can't do this call.");
  1591.          }
  1592.       }
  1593.  
  1594.       cdef = coldefinition;
  1595.  
  1596.       if (cdef->restriction == cr_alwaysfail)
  1597.          goto cdef_failed;
  1598.  
  1599.       switch (ss->kind) {
  1600.          int t, q0, q1, q2, q3, q4, q5, q6, q7;
  1601.  
  1602.          case s2x4:
  1603.             switch (cdef->restriction) {
  1604.                case cr_wave_only:
  1605.                   k = 0;         /* check for real columns */
  1606.                   i = 2;
  1607.                   if (ss->people[0].id1) { k |=  ss->people[0].id1; i &=  ss->people[0].id1; }
  1608.                   if (ss->people[1].id1) { k |=  ss->people[1].id1; i &=  ss->people[1].id1; }
  1609.                   if (ss->people[2].id1) { k |=  ss->people[2].id1; i &=  ss->people[2].id1; }
  1610.                   if (ss->people[3].id1) { k |=  ss->people[3].id1; i &=  ss->people[3].id1; }
  1611.                   if (ss->people[4].id1) { k |= ~ss->people[4].id1; i &= ~ss->people[4].id1; }
  1612.                   if (ss->people[5].id1) { k |= ~ss->people[5].id1; i &= ~ss->people[5].id1; }
  1613.                   if (ss->people[6].id1) { k |= ~ss->people[6].id1; i &= ~ss->people[6].id1; }
  1614.                   if (ss->people[7].id1) { k |= ~ss->people[7].id1; i &= ~ss->people[7].id1; }
  1615.                   if (k & ~i & 2)
  1616.                      goto cdef_failed;
  1617.                   break;
  1618.                case cr_magic_only:
  1619.                   k = 0;         /* check for magic columns */
  1620.                   i = 2;
  1621.                   if (ss->people[0].id1) { k |=  ss->people[0].id1; i &=  ss->people[0].id1; }
  1622.                   if (ss->people[1].id1) { k |= ~ss->people[1].id1; i &= ~ss->people[1].id1; }
  1623.                   if (ss->people[2].id1) { k |= ~ss->people[2].id1; i &= ~ss->people[2].id1; }
  1624.                   if (ss->people[3].id1) { k |=  ss->people[3].id1; i &=  ss->people[3].id1; }
  1625.                   if (ss->people[4].id1) { k |= ~ss->people[4].id1; i &= ~ss->people[4].id1; }
  1626.                   if (ss->people[5].id1) { k |=  ss->people[5].id1; i &=  ss->people[5].id1; }
  1627.                   if (ss->people[6].id1) { k |=  ss->people[6].id1; i &=  ss->people[6].id1; }
  1628.                   if (ss->people[7].id1) { k |= ~ss->people[7].id1; i &= ~ss->people[7].id1; }
  1629.                   if (k & ~i & 2)
  1630.                      goto cdef_failed;
  1631.                   break;
  1632.                case cr_couples_only:
  1633.                   /* check for everyone as a couple */
  1634.                   q0 = 0; q1 = 0;
  1635.                   q4 = 0; q5 = 0;
  1636.                   q2 = 0; q3 = 0;
  1637.                   q6 = 0; q7 = 0;
  1638.                   if (t = ss->people[0].id1) { q0 |= (t^1); q1 |= (t^3); }
  1639.                   if (t = ss->people[7].id1) { q0 |= (t^1); q1 |= (t^3); }
  1640.                   if (t = ss->people[1].id1) { q5 |= (t^1); q4 |= (t^3); }
  1641.                   if (t = ss->people[6].id1) { q5 |= (t^1); q4 |= (t^3); }
  1642.                   if (t = ss->people[2].id1) { q2 |= (t^1); q3 |= (t^3); }
  1643.                   if (t = ss->people[5].id1) { q2 |= (t^1); q3 |= (t^3); }
  1644.                   if (t = ss->people[3].id1) { q6 |= (t^1); q7 |= (t^3); }
  1645.                   if (t = ss->people[4].id1) { q6 |= (t^1); q7 |= (t^3); }
  1646.                   if (((q0&3) && (q1&3)) ||
  1647.                       ((q2&3) && (q3&3)) ||
  1648.                       ((q6&3) && (q7&3)) ||
  1649.                       ((q5&3) && (q4&3)))
  1650.                      goto cdef_failed;
  1651.                   break;
  1652.                case cr_quarterbox_or_col:
  1653.                   k = 0;         /* check for a reasonable "triple cross" setup */
  1654.                   i = 2;
  1655.                   if (ss->people[0].id1) { k |=  ss->people[0].id1;                         }
  1656.                   if (ss->people[1].id1) { k |=  ss->people[1].id1; i &=  ss->people[1].id1; }
  1657.                   if (ss->people[2].id1) { k |=  ss->people[2].id1; i &=  ss->people[2].id1; }
  1658.                   if (ss->people[3].id1) {                         i &=  ss->people[3].id1; }
  1659.                   if (ss->people[4].id1) { k |= ~ss->people[4].id1;                         }
  1660.                   if (ss->people[5].id1) { k |= ~ss->people[5].id1; i &= ~ss->people[5].id1; }
  1661.                   if (ss->people[6].id1) { k |= ~ss->people[6].id1; i &= ~ss->people[6].id1; }
  1662.                   if (ss->people[7].id1) {                         i &= ~ss->people[7].id1; }
  1663.                   if (k & ~i & 2)
  1664.                      goto cdef_failed;
  1665.                   break;
  1666.                case cr_quarterbox_or_magic_col:
  1667.                   k = 0;         /* check for a reasonable "make magic" setup */
  1668.                   i = 2;
  1669.                   if (ss->people[0].id1) {                         i &= ~ss->people[0].id1; }
  1670.                   if (ss->people[1].id1) { k |=  ss->people[1].id1; i &=  ss->people[1].id1; }
  1671.                   if (ss->people[2].id1) { k |=  ss->people[2].id1; i &=  ss->people[2].id1; }
  1672.                   if (ss->people[3].id1) { k |= ~ss->people[3].id1;                         }
  1673.                   if (ss->people[4].id1) {                         i &=  ss->people[4].id1; }
  1674.                   if (ss->people[5].id1) { k |= ~ss->people[5].id1; i &= ~ss->people[5].id1; }
  1675.                   if (ss->people[6].id1) { k |= ~ss->people[6].id1; i &= ~ss->people[6].id1; }
  1676.                   if (ss->people[7].id1) { k |=  ss->people[7].id1;                         }
  1677.                   if (k & ~i & 2)
  1678.                      goto cdef_failed;
  1679.                   break;
  1680.             }
  1681.             break;
  1682.          case s_2x3:
  1683.             switch (cdef->restriction) {
  1684.                case cr_wave_only:
  1685.                   k = 0;         /* check for real columns */
  1686.                   i = 2;
  1687.                   if (ss->people[0].id1) { k |=  ss->people[0].id1; i &=  ss->people[0].id1; }
  1688.                   if (ss->people[1].id1) { k |=  ss->people[1].id1; i &=  ss->people[1].id1; }
  1689.                   if (ss->people[2].id1) { k |=  ss->people[2].id1; i &=  ss->people[2].id1; }
  1690.                   if (ss->people[3].id1) { k |= ~ss->people[3].id1; i &= ~ss->people[3].id1; }
  1691.                   if (ss->people[4].id1) { k |= ~ss->people[4].id1; i &= ~ss->people[4].id1; }
  1692.                   if (ss->people[5].id1) { k |= ~ss->people[5].id1; i &= ~ss->people[5].id1; }
  1693.                   if (k & ~i & 2)
  1694.                      goto cdef_failed;
  1695.                   break;
  1696.             }
  1697.             break;
  1698.       }
  1699.  
  1700.       goto cdef_won;
  1701.  
  1702.       cdef_failed:
  1703.  
  1704.       if (cdef->callarray_flags & CAF__RESTR_UNUSUAL) warn(warn__unusual);
  1705.       else if (cdef->callarray_flags & CAF__RESTR_FORBID) fail("This call is not legal from this formation.");
  1706.       else warn(warn__do_your_part);
  1707.    
  1708.       cdef_won:
  1709.  
  1710.       /* If we have linedefinition also, check for consistency. */
  1711.    
  1712.       if (goodies) {
  1713.          if (goodies->end_setup != cdef->end_setup) {
  1714.             /* ***** should also check the other stupid fields! */
  1715.             switch (ss->kind) {
  1716.                case sdmd:
  1717.                   fail("\"T-bone\" diamond call went to a weird setup.");
  1718.                case s_trngl:
  1719.                   fail("Triangle call went to a weird setup.");
  1720.                case s_2x3: case s_short6:
  1721.                   fail("T-bone 6-person call went to a weird setup.");
  1722.                case s1x8: case s2x4: case s_qtag:
  1723.                   fail("T-bone 8-person call went to a weird setup.");
  1724.                case s1x4:
  1725.                   fail("T-bone 4-person call went to a weird setup.");
  1726.                case s_1x2:
  1727.                   fail("T-bone 2-person call went to a weird setup.");
  1728.                default:
  1729.                   fail("T-bone call went to a weird setup.");
  1730.             }
  1731.          }
  1732.  
  1733.          inconsistent_rotation = (goodies->callarray_flags ^ cdef->callarray_flags) & CAF__ROT;
  1734.       }
  1735.    
  1736.       goodies = cdef;
  1737.    }
  1738.  
  1739.    result->kind = goodies->end_setup;
  1740.    
  1741.    if (result->kind == s_normal_concentric) {         /* ***** this requires an 8-person call definition */
  1742.       setup inners;
  1743.       setup outers;
  1744.       int outer_elongation;
  1745.       setup p1;
  1746.  
  1747.       if (inconsistent_rotation) fail("This call is an inconsistent shape-changer.");
  1748.       if (funny) fail("Sorry, can't do this call 'funny'");
  1749.  
  1750.       clear_people(&p1);
  1751.    
  1752.       for (real_index=0; real_index<8; real_index++) {
  1753.          personrec this_person = ss->people[real_index];
  1754.          if (this_person.id1) {
  1755.             int real_direction = this_person.id1 & 3;
  1756.             int d2 = (this_person.id1 << 1) & 4;
  1757.             northified_index = (real_index ^ d2);
  1758.             z = find_calldef((real_direction & 1) ? cdef : ldef, ss, real_index, real_direction, northified_index);
  1759.             k = ((z >> 4) & 017) ^ (d2 >> 1);
  1760.             install_person(&p1, k, ss, real_index);
  1761.             p1.people[k].id1 = (p1.people[k].id1 & ~(ROLLBITS | 077)) | ((z + real_direction * 011) & 013) | ((z << 14) & ROLLBITS);
  1762.          }
  1763.       }
  1764.    
  1765.       for (k=0; k<4; k++) {
  1766.          (void) copy_person(&inners, k, &p1, k);
  1767.          (void) copy_person(&outers, k, &p1, k+4);
  1768.       }
  1769.  
  1770.       inners.setupflags = 0;
  1771.       outers.setupflags = 0;
  1772.       inners.kind = goodies->end_setup_in;
  1773.       outers.kind = goodies->end_setup_out;
  1774.       inners.rotation = goodies->callarray_flags & CAF__ROT;
  1775.       outers.rotation = (goodies->callarray_flags & CAF__ROT_OUT) ? 1 : 0;
  1776.    
  1777.       /* For calls defined by array with concentric end setup, the "parallel_conc_end" flag
  1778.          turns on the outer elongation. */
  1779.       outer_elongation = outers.rotation;
  1780.       if (callspec->callflags & cflag__parallel_conc_end) outer_elongation ^= 1;
  1781.  
  1782.       normalize_concentric(schema_concentric, 1, &inners, &outers, outer_elongation, result);
  1783.  
  1784.       goto fixup;
  1785.    }
  1786.    else {   
  1787.       int lilresult_mask;
  1788.       setup_kind tempkind;
  1789.  
  1790.       result->rotation = goodies->callarray_flags & CAF__ROT;
  1791.  
  1792.       collision_mask = 0;
  1793.       result_mask = 0;
  1794.       num = setup_limits[ss->kind]+1;
  1795.       halfnum = num >> 1;
  1796.       numout = setup_limits[result->kind]+1;
  1797.       halfnumout = numout >> 1;
  1798.       tempkind = result->kind;
  1799.       lilresult_mask = 0;
  1800.  
  1801.       if (funny) {
  1802.          if ((ss->kind != result->kind) || result->rotation || inconsistent_rotation)
  1803.             fail("Can't do 'funny' shape-changer.");
  1804.       }
  1805.  
  1806.       if (four_way_startsetup) {
  1807.          special_4_way_symm(ldef, ss, newpersonlist, newplacelist, &lilresult_mask, result);
  1808.       }
  1809.       else if (ss->kind == s_trngl) {
  1810.          if (inconsistent_rotation) fail("This call is an inconsistent shape-changer.");
  1811.          special_triangle(cdef, ldef, ss, newpersonlist, newplacelist);
  1812.  
  1813.          /* Check whether the call went into the other triangle.  If so, it
  1814.             must have done so completely. */
  1815.          if (newplacelist[0] >=3 || newplacelist[1] >=3 || newplacelist[2] >=3) {
  1816.             result->rotation += 2;
  1817.  
  1818.             for (i=0; i<3; i++) {
  1819.                if (newplacelist[i] >=0) {
  1820.                   newplacelist[i] -= 3;
  1821.                   if (newplacelist[i] < 0)
  1822.                      fail("Call went into other triangle????.");
  1823.                   newpersonlist[i].id1 = rotperson(newpersonlist[i].id1, 022);
  1824.                }
  1825.             }
  1826.          }
  1827.       }
  1828.       else {
  1829.          int *final_translatec = identity;
  1830.          int *final_translatel = identity;
  1831.          int rotfudge = 0;
  1832.  
  1833.          if (inconsistent_rotation) {
  1834.             if (result->kind == s2x4) {
  1835.                result->kind = s4x4;
  1836.                tempkind = result->kind;
  1837.                final_translatec = ftc2x4;
  1838.  
  1839.                if (goodies->callarray_flags & CAF__ROT) {
  1840.                   final_translatel = &ftl2x4[0];
  1841.                   rotfudge = 3;
  1842.                }
  1843.                else {
  1844.                   final_translatel = &ftl2x4[4];
  1845.                   rotfudge = 1;
  1846.                }
  1847.             }
  1848.             else
  1849.                fail("This call is an inconsistent shape-changer.");
  1850.          }
  1851.  
  1852.          for (real_index=0; real_index<num; real_index++) {
  1853.             int kt;
  1854.             personrec this_person = ss->people[real_index];
  1855.             newpersonlist[real_index].id1 = 0;
  1856.             newpersonlist[real_index].id2 = 0;
  1857.             if (this_person.id1) {
  1858.                int final_direction;
  1859.                int real_direction = this_person.id1 & 3;
  1860.                int d2 = ((this_person.id1 >> 1) & 1) * halfnum;
  1861.                int d2out = ((this_person.id1 >> 1) & 1) * halfnumout;
  1862.                northified_index = (real_index + d2) % num;
  1863.                z = find_calldef((real_direction & 1) ? cdef : ldef, ss, real_index, real_direction, northified_index);
  1864.                k = (((z >> 4) & 017) + d2out) % numout;
  1865.                final_direction = real_direction;
  1866.                /* Line people are going into wrong rotation. */
  1867.                if (!(real_direction & 1)) final_direction = (final_direction + rotfudge) & 3;
  1868.                newpersonlist[real_index].id1 = (this_person.id1 & ~(ROLLBITS | 077)) | ((z + final_direction * 011) & 013) | ((z << 14) & ROLLBITS);
  1869.                newpersonlist[real_index].id2 = this_person.id2;
  1870.                kt = ((real_direction & 1) ? final_translatec : final_translatel) [k];
  1871.                newplacelist[real_index] = kt;
  1872.                lilresult_mask |= (1 << kt);
  1873.             }
  1874.          }
  1875.       }
  1876.  
  1877.       /* If the result setup size is larger than the starting setup size, we assume that this call
  1878.          has a concocted result setup (e.g. squeeze the galaxy, unwrap the galaxy, change your
  1879.          image), and we try to compress it.  We claim that, if the result size given
  1880.          in the calls database is bigger than the starting size, as it is for those calls, we
  1881.          don't really want that big setup, but want to compress it immediately if possible.
  1882.          Q: Why don't we just let the natural setup normalization that will occur later do this
  1883.          for us?  A: That only happens at the top level.  In this case, we consider the compression
  1884.          to be part of doing the call.  If we someday were able to do a reverse flip of split
  1885.          phantom galaxies, we would want each galaxy to compress itself to a 2x4 before
  1886.          reassembling them.
  1887.       If we handle 4x4 start setups in the future, we would NOT want to compress
  1888.          a 4x4 to a 2x4 after a 16-matrix circulate!!!!!  This is why we compare the beginning and
  1889.          ending setup sizes. */
  1890.  
  1891.       if (setup_limits[ss->kind] < setup_limits[result->kind]) {
  1892.          if (result->kind == s4x4) {
  1893.             /* See if people landed on 2x4 spots. */
  1894.             if ((lilresult_mask & 0x7171) == 0) {
  1895.                result->kind = s2x4;
  1896.                for (real_index=0; real_index<num; real_index++) {
  1897.                   if (ss->people[real_index].id1) {
  1898.                      newplacelist[real_index] = galtranslateh[newplacelist[real_index]];
  1899.                   }
  1900.                }
  1901.             }
  1902.             else if ((lilresult_mask & 0x1717) == 0) {
  1903.                result->kind = s2x4;
  1904.                for (real_index=0; real_index<num; real_index++) {
  1905.                   if (ss->people[real_index].id1) {
  1906.                      newplacelist[real_index] = galtranslatev[newplacelist[real_index]];
  1907.                      newpersonlist[real_index].id1 = rotccw(newpersonlist[real_index].id1);
  1908.                   }
  1909.                }
  1910.                result->rotation++;
  1911.             }
  1912.             else {
  1913.                /* If fakery occurred and we were not able to compress it, that is an error.  It
  1914.                   means the points got confused on a reverse flip the galaxy.  If we were not able
  1915.                   to compress a 4x4 but no fakery occurred, we let it pass.  That simply means
  1916.                   that the unwrappers were T-boned in an unwrap the galaxy, so they led out
  1917.                   in strange directions.  Is this the right thing to do?  Do we want to allow
  1918.                   T-boned reverse flip?  Probably not. */
  1919.       
  1920.                if (tempkind != s4x4) fail("Galaxy call went to improperly-formed setup.");
  1921.             }
  1922.          }
  1923.          else if (result->kind == s_hyperglass) {
  1924.             /* We check for 1x4's before checking for diamonds. */
  1925.             if ((lilresult_mask & 07474) == 0) {
  1926.                result->kind = s1x4;
  1927.                for (real_index=0; real_index<num; real_index++) {
  1928.                   if (ss->people[real_index].id1) newplacelist[real_index] = linehyperh[newplacelist[real_index]];
  1929.                }
  1930.             }
  1931.             else if ((lilresult_mask & 04747) == 0) {
  1932.                result->kind = s1x4;
  1933.                for (real_index=0; real_index<num; real_index++) {
  1934.                   if (ss->people[real_index].id1) {
  1935.                      newplacelist[real_index] = linehyperv[newplacelist[real_index]];
  1936.                      newpersonlist[real_index].id1 = rotccw(newpersonlist[real_index].id1);
  1937.                   }
  1938.                }
  1939.                result->rotation++;
  1940.             }
  1941.             else if ((lilresult_mask & 05656) == 0) {
  1942.                result->kind = sdmd;
  1943.                for (real_index=0; real_index<num; real_index++) {
  1944.                   if (ss->people[real_index].id1) newplacelist[real_index] = dmdhyperh[newplacelist[real_index]];
  1945.                }
  1946.             }
  1947.             else if ((lilresult_mask & 06565) == 0) {
  1948.                result->kind = sdmd;
  1949.                for (real_index=0; real_index<num; real_index++) {
  1950.                   if (ss->people[real_index].id1) {
  1951.                      newplacelist[real_index] = dmdhyperv[newplacelist[real_index]];
  1952.                      newpersonlist[real_index].id1 = rotccw(newpersonlist[real_index].id1);
  1953.                   }
  1954.                }
  1955.                result->rotation++;
  1956.             }
  1957.             else if ((lilresult_mask & 01212) == 0) {
  1958.                result->kind = s_hrglass;
  1959.                for (real_index=0; real_index<num; real_index++) {
  1960.                   if (ss->people[real_index].id1) newplacelist[real_index] = galhyperh[newplacelist[real_index]];
  1961.                }
  1962.             }
  1963.             else if ((lilresult_mask & 02121) == 0) {
  1964.                result->kind = s_hrglass;
  1965.                for (real_index=0; real_index<num; real_index++) {
  1966.                   if (ss->people[real_index].id1) {
  1967.                      newplacelist[real_index] = galhyperv[newplacelist[real_index]];
  1968.                      newpersonlist[real_index].id1 = rotccw(newpersonlist[real_index].id1);
  1969.                   }
  1970.                }
  1971.                result->rotation++;
  1972.             }
  1973.             else if ((lilresult_mask & 05555) == 0) {
  1974.                result->kind = s_star;
  1975.                for (real_index=0; real_index<num; real_index++) {
  1976.                   if (ss->people[real_index].id1) newplacelist[real_index] = starhyperh[newplacelist[real_index]];
  1977.                }
  1978.             }
  1979.             else if ((lilresult_mask & 06666) == 0) {
  1980.                result->kind = s_star;        /* Actually, this is a star with all people sort of far away
  1981.                                              from the center.  We may need to invent a new setup, "farstar". */
  1982.                for (real_index=0; real_index<num; real_index++) {
  1983.                   if (ss->people[real_index].id1) newplacelist[real_index] = fstarhyperh[newplacelist[real_index]];
  1984.                }
  1985.             }
  1986.             else
  1987.                fail("Call went to improperly-formed setup.");
  1988.          }
  1989.          else if (result->kind == s_2x3) {
  1990.             /* This call turned a smaller setup (like a 1x4) into a 2x3.
  1991.                It is presumably a call like "pair the line" or "step and slide".
  1992.                Flag the result setup so that the appropriate phantom-squashing
  1993.                will take place if two of these results are placed end-to-end. */
  1994.             resultflags |= RESULTFLAG__EXPAND_TO_2X3;
  1995.          }
  1996.       }
  1997.    }
  1998.  
  1999.    /* Install all the people. */
  2000.  
  2001.    numout = setup_limits[result->kind]+1;
  2002.  
  2003.    for (real_index=0; real_index<num; real_index++) {
  2004.       personrec newperson = newpersonlist[real_index];
  2005.       if (newperson.id1) {
  2006.          if (funny) {
  2007.             if (newperson.id1 != -1) {           /* We only handle people who haven't been erased. */
  2008.                k = real_index;
  2009.                j = real_index;               /* j will move twice as fast as k, looking for a loop not containing starting point. */
  2010.                do {
  2011.                   j = newplacelist[j];
  2012.                   /* If hit a phantom, we can't proceed. */
  2013.                   if (!newpersonlist[j].id1) fail("Can't do 'funny' call with phantoms.");
  2014.                   /* If hit an erased person, we have clearly hit a loop not containing starting point. */
  2015.                   else if (newpersonlist[j].id1 == -1) break;
  2016.                   j = newplacelist[j];
  2017.                   if (!newpersonlist[j].id1) fail("Can't do 'funny' call with phantoms.");
  2018.                   else if (newpersonlist[j].id1 == -1) break;
  2019.                   k = newplacelist[k];
  2020.                   if (k == real_index) goto funny_win;
  2021.                } while (k != j);
  2022.  
  2023.                /* This person can't move, because he moves into a loop not conaining his starting point. */
  2024.                k = real_index;
  2025.                newperson.id1 = (ss->people[real_index].id1 & ~ROLLBITS) | ROLLBITM;
  2026.                newperson.id2 = ss->people[real_index].id2;
  2027.                result->people[k] = newperson;
  2028.                newpersonlist[k].id1 = -1;
  2029.                funny_ok1 = TRUE;    /* Someone decided not to move.  Hilarious. */
  2030.                goto funny_end;
  2031.  
  2032.                funny_win:
  2033.                /* Move the entire loop, replacing people with -1. */
  2034.                k = real_index;
  2035.                j = 0;      /* See how long the loop is. */
  2036.                do {
  2037.                   newperson = newpersonlist[k];
  2038.                   newpersonlist[k].id1 = -1;
  2039.                   k = newplacelist[k];
  2040.                   result->people[k] = newperson;
  2041.                   j++;
  2042.                } while (k != real_index);
  2043.  
  2044.                if (j > 2) warn(warn__hard_funny);
  2045.                funny_ok2 = TRUE;    /* Someone was able to move.  Hysterical. */
  2046.                                     /* Actually, I don't see how this test can fail.
  2047.                                        Someone can always move! */
  2048.  
  2049.                funny_end: ;
  2050.             }
  2051.          }
  2052.          else {              /* Un-funny move. */
  2053.             k = newplacelist[real_index];
  2054.             if (result->people[k].id1 == 0) {
  2055.                result->people[k] = newperson;
  2056.                result_mask |= (1 << k);
  2057.             }
  2058.             else if ((callspec->callflags & cflag__take_right_hands) && (numout <= 12) && (result->people[k+12].id1 == 0)) {
  2059.                /* Collisions are legal.  Store the person in the overflow area
  2060.                   (12 higher than the main area, which is why we only permit
  2061.                   this if the result setup size is <= 12) and record the fact
  2062.                   in the collision_mask so we can figure out what to do. */
  2063.                result->people[k+12] = newperson;
  2064.                collision_mask |= (1 << k);
  2065.                collision_index = k;        /* In case we need to report a mundane collision. */
  2066.             }
  2067.             else {
  2068.                collision_person1 = result->people[k].id1;
  2069.                collision_person2 = newperson.id1;
  2070.                error_message1[0] = '\0';
  2071.                error_message2[0] = '\0';
  2072.                longjmp(longjmp_ptr->the_buf, 3);
  2073.             }
  2074.          }
  2075.       }
  2076.    }
  2077.  
  2078.    if (funny) {
  2079.       if (!funny_ok1 || !funny_ok2) warn(warn__not_funny);
  2080.    }
  2081.    else {
  2082.       if (collision_mask) fix_collision(collision_mask, collision_index, result_mask, result);
  2083.    }
  2084.    
  2085.    fixup:
  2086.  
  2087.    reinstate_rotation(ss, result);
  2088.    goto un_mirror;
  2089.  
  2090.    divide_us:
  2091.  
  2092.    divided_setup_move(ss, parseptr, callspec, final_concepts, division_maps, phantest_ok, TRUE, result);
  2093.    goto un_mirror;
  2094.  
  2095.    divide_us_no_recompute:
  2096.  
  2097.    divided_setup_move(ss, parseptr, callspec, final_concepts, division_maps, phantest_ok, FALSE, result);
  2098.  
  2099.    /* If expansion to a 2x3 occurred (because the call was, for example, a "pair the line"),
  2100.       and the two 2x3's are end-to-end in a 2x6, see if we can squash phantoms.  We squash both
  2101.       internal (the center triple box) and external ones.  The external ones would probably have
  2102.       been squashed anyway due to the top level normalization, but we want the to occur
  2103.       immediately, not just at the top level, though we can't think of a concrete example
  2104.       in which it makes a difference. */
  2105.    if ((result->setupflags & RESULTFLAG__EXPAND_TO_2X3) && (result->kind == s2x6)) {
  2106.       if (!(result->people[2].id1 | result->people[3].id1 | result->people[8].id1 | result->people[9].id1)) {
  2107.          /* Inner spots are empty. */
  2108.          result->kind = s2x4;
  2109.          (void) copy_person(result, 2, result, 4);            /* careful -- order is important */
  2110.          (void) copy_person(result, 3, result, 5);
  2111.          (void) copy_person(result, 4, result, 6);
  2112.          (void) copy_person(result, 5, result, 7);
  2113.          (void) copy_person(result, 6, result, 10);
  2114.          (void) copy_person(result, 7, result, 11);
  2115.       }
  2116.       else if (!(result->people[0].id1 | result->people[5].id1 | result->people[6].id1 | result->people[11].id1)) {
  2117.          /* Outer spots are empty. */
  2118.          result->kind = s2x4;
  2119.          (void) copy_person(result, 0, result, 1);            /* careful -- order is important */
  2120.          (void) copy_person(result, 1, result, 2);
  2121.          (void) copy_person(result, 2, result, 3);
  2122.          (void) copy_person(result, 3, result, 4);
  2123.          (void) copy_person(result, 4, result, 7);
  2124.          (void) copy_person(result, 5, result, 8);
  2125.          (void) copy_person(result, 6, result, 9);
  2126.          (void) copy_person(result, 7, result, 10);
  2127.       }
  2128.    }
  2129.  
  2130.    un_mirror:
  2131.  
  2132.    /* We take out any elongation info that divided_setup_move may have put in
  2133.       and override it with the correct info. */
  2134.  
  2135.    result->setupflags &= ~RESULTFLAG__ELONGATE_MASK;
  2136.    result->setupflags |= resultflags | desired_elongation;
  2137. }
  2138.